openmates 0.18.0-alpha.2 → 0.18.0-alpha.4
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/dist/{chunk-XKIFO4JO.js → chunk-EKALVG2T.js} +298 -119
- package/dist/{cli-BMrmfKIF.d.ts → cli-BLFXUeuE.d.ts} +3 -0
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/package.json +3 -1
|
@@ -1015,6 +1015,10 @@ var OpenMatesHttpClient = class {
|
|
|
1015
1015
|
getCookieMap() {
|
|
1016
1016
|
return Object.fromEntries(this.cookies.entries());
|
|
1017
1017
|
}
|
|
1018
|
+
replaceCookies(cookies) {
|
|
1019
|
+
this.cookies.clear();
|
|
1020
|
+
for (const [name, value] of Object.entries(cookies)) this.cookies.set(name, value);
|
|
1021
|
+
}
|
|
1018
1022
|
async get(path2, headers = {}) {
|
|
1019
1023
|
return this.request("GET", path2, void 0, headers);
|
|
1020
1024
|
}
|
|
@@ -1194,8 +1198,10 @@ import {
|
|
|
1194
1198
|
readdirSync,
|
|
1195
1199
|
readFileSync as readFileSync2,
|
|
1196
1200
|
rmSync,
|
|
1201
|
+
renameSync,
|
|
1197
1202
|
writeFileSync
|
|
1198
1203
|
} from "fs";
|
|
1204
|
+
import lockfile from "proper-lockfile";
|
|
1199
1205
|
import { createHash as createHash4 } from "crypto";
|
|
1200
1206
|
import { homedir as homedir2 } from "os";
|
|
1201
1207
|
import { isAbsolute, join, resolve } from "path";
|
|
@@ -1483,7 +1489,55 @@ function saveAnonymousId(anonymousId) {
|
|
|
1483
1489
|
createdAt: Math.floor(Date.now() / 1e3)
|
|
1484
1490
|
});
|
|
1485
1491
|
}
|
|
1486
|
-
|
|
1492
|
+
var SESSION_LOCK_STALE_MS = 3e4;
|
|
1493
|
+
var SESSION_LOCK_POLL_MS = 50;
|
|
1494
|
+
async function withSessionRefreshLock(operation) {
|
|
1495
|
+
const path2 = join(ensureStateDir(), "session.json");
|
|
1496
|
+
const release2 = await lockfile.lock(`${path2}.refresh`, {
|
|
1497
|
+
realpath: false,
|
|
1498
|
+
stale: SESSION_LOCK_STALE_MS,
|
|
1499
|
+
retries: { retries: 600, factor: 1, minTimeout: SESSION_LOCK_POLL_MS, maxTimeout: SESSION_LOCK_POLL_MS }
|
|
1500
|
+
});
|
|
1501
|
+
try {
|
|
1502
|
+
return await operation();
|
|
1503
|
+
} finally {
|
|
1504
|
+
await release2();
|
|
1505
|
+
}
|
|
1506
|
+
}
|
|
1507
|
+
function saveSession(session, options = {}) {
|
|
1508
|
+
const path2 = join(ensureStateDir(), "session.json");
|
|
1509
|
+
let release2;
|
|
1510
|
+
const waitCell = new Int32Array(new SharedArrayBuffer(4));
|
|
1511
|
+
for (let attempt = 0; ; attempt++) {
|
|
1512
|
+
try {
|
|
1513
|
+
release2 = lockfile.lockSync(`${path2}.write`, { realpath: false, stale: SESSION_LOCK_STALE_MS });
|
|
1514
|
+
break;
|
|
1515
|
+
} catch (error) {
|
|
1516
|
+
if (error.code !== "ELOCKED" || attempt >= 100) throw error;
|
|
1517
|
+
Atomics.wait(waitCell, 0, 0, SESSION_LOCK_POLL_MS);
|
|
1518
|
+
}
|
|
1519
|
+
}
|
|
1520
|
+
try {
|
|
1521
|
+
const current = readJsonFile(path2);
|
|
1522
|
+
if (current && !options.replace) {
|
|
1523
|
+
if (current.sessionId !== session.sessionId || current.hashedEmail !== session.hashedEmail || current.apiUrl !== session.apiUrl) {
|
|
1524
|
+
throw new Error("Login session changed in another process. Retry the command using the current profile.");
|
|
1525
|
+
}
|
|
1526
|
+
if (options.expectedRefreshToken !== void 0) {
|
|
1527
|
+
if (current.cookies.auth_refresh_token !== options.expectedRefreshToken) {
|
|
1528
|
+
throw new Error("Login credentials changed during refresh. Retry with the current profile.");
|
|
1529
|
+
}
|
|
1530
|
+
} else {
|
|
1531
|
+
session.cookies = { ...current.cookies };
|
|
1532
|
+
session.wsToken = current.wsToken;
|
|
1533
|
+
}
|
|
1534
|
+
}
|
|
1535
|
+
writeSession(session);
|
|
1536
|
+
} finally {
|
|
1537
|
+
release2();
|
|
1538
|
+
}
|
|
1539
|
+
}
|
|
1540
|
+
function writeSession(session) {
|
|
1487
1541
|
const filePath = join(ensureStateDir(), "session.json");
|
|
1488
1542
|
const result = storeMasterKey(session.masterKeyExportedB64, resolveKeyStorageId(session.hashedEmail));
|
|
1489
1543
|
const onDisk = {
|
|
@@ -1516,7 +1570,13 @@ function saveSession(session) {
|
|
|
1516
1570
|
onDisk.emailEncryptionKeyB64 = session.emailEncryptionKeyB64;
|
|
1517
1571
|
}
|
|
1518
1572
|
}
|
|
1519
|
-
|
|
1573
|
+
const temporary = `${filePath}.${process.pid}.tmp`;
|
|
1574
|
+
try {
|
|
1575
|
+
writeJsonFile(temporary, onDisk);
|
|
1576
|
+
renameSync(temporary, filePath);
|
|
1577
|
+
} finally {
|
|
1578
|
+
rmSync(temporary, { force: true });
|
|
1579
|
+
}
|
|
1520
1580
|
if (result.type !== "plaintext") {
|
|
1521
1581
|
process.stderr.write("Decrypting data...\n");
|
|
1522
1582
|
}
|
|
@@ -7509,7 +7569,9 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
7509
7569
|
apiUrl;
|
|
7510
7570
|
session;
|
|
7511
7571
|
http;
|
|
7572
|
+
explicitSession;
|
|
7512
7573
|
constructor(options = {}) {
|
|
7574
|
+
this.explicitSession = options.session !== void 0;
|
|
7513
7575
|
const diskSession = options.session ?? this.getValidSessionFromDisk();
|
|
7514
7576
|
this.apiUrl = (options.apiUrl ?? process.env.OPENMATES_API_URL ?? diskSession?.apiUrl ?? loadDefaultServerApiUrl() ?? DEFAULT_API_URL).replace(/\/$/, "");
|
|
7515
7577
|
this.session = diskSession;
|
|
@@ -8570,31 +8632,34 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
8570
8632
|
};
|
|
8571
8633
|
await this.hydrateEmailEncryptionKey(session);
|
|
8572
8634
|
this.session = session;
|
|
8573
|
-
saveSession(session);
|
|
8635
|
+
saveSession(session, { replace: true });
|
|
8574
8636
|
}
|
|
8575
8637
|
async whoAmI() {
|
|
8576
|
-
|
|
8577
|
-
|
|
8578
|
-
|
|
8579
|
-
|
|
8580
|
-
|
|
8581
|
-
|
|
8582
|
-
|
|
8583
|
-
|
|
8638
|
+
return this.withFreshStoredSession(async () => {
|
|
8639
|
+
const session = this.requireSession();
|
|
8640
|
+
const previousRefreshToken = session.cookies.auth_refresh_token;
|
|
8641
|
+
const response = await this.http.post(
|
|
8642
|
+
"/v1/auth/session",
|
|
8643
|
+
{ session_id: session.sessionId },
|
|
8644
|
+
this.getCliRequestHeaders()
|
|
8645
|
+
);
|
|
8646
|
+
if (!response.ok || !response.data.success) {
|
|
8647
|
+
if (response.status === 502 || response.status === 503 || response.status === 504) {
|
|
8648
|
+
throw new Error(
|
|
8649
|
+
`Session validation temporarily unavailable (HTTP ${response.status}). The API may be restarting; retry shortly.`
|
|
8650
|
+
);
|
|
8651
|
+
}
|
|
8584
8652
|
throw new Error(
|
|
8585
|
-
`Session validation
|
|
8653
|
+
`Session validation failed (HTTP ${response.status}): ${response.data.message ?? "invalid session"}${response.data.re_auth_reason ? ` (${response.data.re_auth_reason})` : ""}. Please run \`${this.loginRecoveryCommand()}\`.`
|
|
8586
8654
|
);
|
|
8587
8655
|
}
|
|
8588
|
-
|
|
8589
|
-
|
|
8590
|
-
|
|
8591
|
-
|
|
8592
|
-
|
|
8593
|
-
|
|
8594
|
-
}
|
|
8595
|
-
session.cookies = this.http.getCookieMap();
|
|
8596
|
-
saveSession(session);
|
|
8597
|
-
return response.data.user ?? {};
|
|
8656
|
+
if (response.data.ws_token) {
|
|
8657
|
+
session.wsToken = response.data.ws_token;
|
|
8658
|
+
}
|
|
8659
|
+
session.cookies = this.http.getCookieMap();
|
|
8660
|
+
saveSession(session, { expectedRefreshToken: previousRefreshToken });
|
|
8661
|
+
return response.data.user ?? {};
|
|
8662
|
+
});
|
|
8598
8663
|
}
|
|
8599
8664
|
async getTopicPreferences() {
|
|
8600
8665
|
const user = await this.whoAmI();
|
|
@@ -8734,7 +8799,7 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
8734
8799
|
authorizerDeviceName: null,
|
|
8735
8800
|
autoLogoutMinutes: null
|
|
8736
8801
|
};
|
|
8737
|
-
saveSession(session);
|
|
8802
|
+
saveSession(session, { replace: true });
|
|
8738
8803
|
this.session = session;
|
|
8739
8804
|
return {
|
|
8740
8805
|
success: true,
|
|
@@ -13974,8 +14039,9 @@ Required: ${schema.required.join(", ")}`
|
|
|
13974
14039
|
const session = this.requireSession();
|
|
13975
14040
|
const currentCookies = this.http.getCookieMap();
|
|
13976
14041
|
if (JSON.stringify(session.cookies) !== JSON.stringify(currentCookies)) {
|
|
14042
|
+
const previousRefreshToken = session.cookies.auth_refresh_token;
|
|
13977
14043
|
session.cookies = currentCookies;
|
|
13978
|
-
saveSession(session);
|
|
14044
|
+
saveSession(session, { expectedRefreshToken: previousRefreshToken });
|
|
13979
14045
|
}
|
|
13980
14046
|
return session;
|
|
13981
14047
|
}
|
|
@@ -14445,9 +14511,30 @@ Required: ${schema.required.join(", ")}`
|
|
|
14445
14511
|
session.userEmailSalt
|
|
14446
14512
|
);
|
|
14447
14513
|
}
|
|
14514
|
+
async withFreshStoredSession(operation) {
|
|
14515
|
+
return withSessionRefreshLock(async () => {
|
|
14516
|
+
const previous = this.requireSession();
|
|
14517
|
+
const current = loadSession();
|
|
14518
|
+
if (!current && !this.explicitSession) {
|
|
14519
|
+
throw new Error("Login session was removed. Log in to the current profile before retrying.");
|
|
14520
|
+
}
|
|
14521
|
+
if (current && !this.explicitSession) {
|
|
14522
|
+
if (current.hashedEmail !== previous.hashedEmail || current.apiUrl !== previous.apiUrl) {
|
|
14523
|
+
throw new Error("Login account changed in another process. Retry using the current profile.");
|
|
14524
|
+
}
|
|
14525
|
+
this.session = current;
|
|
14526
|
+
this.http.replaceCookies(current.cookies);
|
|
14527
|
+
}
|
|
14528
|
+
return operation();
|
|
14529
|
+
});
|
|
14530
|
+
}
|
|
14531
|
+
loginRecoveryCommand() {
|
|
14532
|
+
const profile = process.env.OPENMATES_PROFILE?.trim();
|
|
14533
|
+
return profile ? `openmates --profile ${profile} login` : "openmates login";
|
|
14534
|
+
}
|
|
14448
14535
|
requireSession() {
|
|
14449
14536
|
if (!this.session) {
|
|
14450
|
-
throw new Error(
|
|
14537
|
+
throw new Error(`Not logged in. Run \`${this.loginRecoveryCommand()}\`.`);
|
|
14451
14538
|
}
|
|
14452
14539
|
return this.session;
|
|
14453
14540
|
}
|
|
@@ -14527,24 +14614,30 @@ Required: ${schema.required.join(", ")}`
|
|
|
14527
14614
|
* This method fetches a fresh ws_token and captures any rotated cookies.
|
|
14528
14615
|
*/
|
|
14529
14616
|
async refreshWsToken() {
|
|
14530
|
-
|
|
14531
|
-
|
|
14532
|
-
|
|
14533
|
-
res
|
|
14534
|
-
|
|
14535
|
-
|
|
14536
|
-
|
|
14537
|
-
|
|
14538
|
-
|
|
14539
|
-
|
|
14540
|
-
|
|
14541
|
-
|
|
14542
|
-
|
|
14543
|
-
|
|
14544
|
-
|
|
14545
|
-
|
|
14546
|
-
|
|
14547
|
-
|
|
14617
|
+
return this.withFreshStoredSession(async () => {
|
|
14618
|
+
const session = this.requireSession();
|
|
14619
|
+
const previousRefreshToken = session.cookies.auth_refresh_token;
|
|
14620
|
+
let res;
|
|
14621
|
+
try {
|
|
14622
|
+
res = await this.http.post("/v1/auth/session", { session_id: session.sessionId }, this.getCliRequestHeaders());
|
|
14623
|
+
} catch {
|
|
14624
|
+
return null;
|
|
14625
|
+
}
|
|
14626
|
+
if (res.status >= 500) {
|
|
14627
|
+
throw new Error(`Session validation temporarily unavailable (HTTP ${res.status}). Retry shortly.`);
|
|
14628
|
+
}
|
|
14629
|
+
if (!res.ok || res.data.success === false) {
|
|
14630
|
+
purgeLocalPrivateData();
|
|
14631
|
+
this.session = null;
|
|
14632
|
+
throw new Error(`Session expired or invalid. Please run \`${this.loginRecoveryCommand()}\` to re-authenticate.`);
|
|
14633
|
+
}
|
|
14634
|
+
if (res.data.ws_token) {
|
|
14635
|
+
session.wsToken = res.data.ws_token;
|
|
14636
|
+
}
|
|
14637
|
+
session.cookies = this.http.getCookieMap();
|
|
14638
|
+
saveSession(session, { expectedRefreshToken: previousRefreshToken });
|
|
14639
|
+
return typeof res.data.user?.id === "string" ? res.data.user.id : typeof res.data.user?.user_id === "string" ? res.data.user.user_id : null;
|
|
14640
|
+
});
|
|
14548
14641
|
}
|
|
14549
14642
|
/**
|
|
14550
14643
|
* Ensure the local sync cache is up to date. If the cache is fresh,
|
|
@@ -20131,12 +20224,12 @@ var ACCOUNT_EXPORT_FORBIDDEN_VALUE_PATTERNS = [
|
|
|
20131
20224
|
];
|
|
20132
20225
|
async function writeAccountExportArchive(bundle, flags = {}) {
|
|
20133
20226
|
const { mkdir: mkdir2, writeFile: writeFile2 } = await import("fs/promises");
|
|
20134
|
-
const { join:
|
|
20227
|
+
const { join: join12, dirname: dirname11 } = await import("path");
|
|
20135
20228
|
const exportId = safeArchiveSegment(String(bundle.export.export_id ?? `export-${Date.now()}`));
|
|
20136
20229
|
const archiveFormat = flags.format === "directory" ? "directory" : "zip";
|
|
20137
20230
|
const password = typeof flags.password === "string" && flags.password.length > 0 ? flags.password : null;
|
|
20138
20231
|
if (password && archiveFormat !== "zip") throw new Error("Password-protected account export is only supported for zip format.");
|
|
20139
|
-
const outputPath = typeof flags.output === "string" ? flags.output :
|
|
20232
|
+
const outputPath = typeof flags.output === "string" ? flags.output : join12(process.cwd(), archiveFormat === "zip" ? `openmates-account-export-${exportId}${password ? ".zip.enc" : ".zip"}` : `openmates-account-export-${exportId}`);
|
|
20140
20233
|
const zip = archiveFormat === "zip" ? new JSZip3() : null;
|
|
20141
20234
|
const writtenFiles = [];
|
|
20142
20235
|
async function writeArchiveText(relativePath, content) {
|
|
@@ -20147,8 +20240,8 @@ async function writeAccountExportArchive(bundle, flags = {}) {
|
|
|
20147
20240
|
return;
|
|
20148
20241
|
}
|
|
20149
20242
|
const stagingDir = outputPath;
|
|
20150
|
-
const fullPath =
|
|
20151
|
-
await mkdir2(
|
|
20243
|
+
const fullPath = join12(stagingDir, relativePath);
|
|
20244
|
+
await mkdir2(dirname11(fullPath), { recursive: true });
|
|
20152
20245
|
await writeFile2(fullPath, content, "utf-8");
|
|
20153
20246
|
writtenFiles.push(relativePath);
|
|
20154
20247
|
}
|
|
@@ -20165,7 +20258,7 @@ async function writeAccountExportArchive(bundle, flags = {}) {
|
|
|
20165
20258
|
}
|
|
20166
20259
|
await writeAccountExportChatFiles(domainPayloads.chats ?? [], writeArchiveText);
|
|
20167
20260
|
if (archiveFormat === "directory") return { output: outputPath, format: "directory", files: writtenFiles.length };
|
|
20168
|
-
await mkdir2(
|
|
20261
|
+
await mkdir2(dirname11(outputPath), { recursive: true });
|
|
20169
20262
|
const zipBuffer = await zip.generateAsync({ type: "nodebuffer", compression: "DEFLATE" });
|
|
20170
20263
|
await writeFile2(outputPath, password ? encryptZipBuffer(zipBuffer, password) : zipBuffer);
|
|
20171
20264
|
return { output: outputPath, format: "zip", files: writtenFiles.length, ...password ? { encrypted: true } : {} };
|
|
@@ -24298,9 +24391,9 @@ var OpenMatesBenchmark = class {
|
|
|
24298
24391
|
// src/cli.ts
|
|
24299
24392
|
import { createInterface as createInterface5 } from "readline/promises";
|
|
24300
24393
|
import { stdin as stdin3, stdout as stdout2 } from "process";
|
|
24301
|
-
import { existsSync as existsSync13, readFileSync as readFileSync12, realpathSync as realpathSync2, writeFileSync as
|
|
24302
|
-
import { fileURLToPath as
|
|
24303
|
-
import { basename as
|
|
24394
|
+
import { existsSync as existsSync13, readFileSync as readFileSync12, realpathSync as realpathSync2, writeFileSync as writeFileSync10 } from "fs";
|
|
24395
|
+
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
24396
|
+
import { basename as basename4, dirname as dirname10 } from "path";
|
|
24304
24397
|
import { createHash as createHash14, randomBytes as randomBytes9, randomUUID as randomUUID15 } from "crypto";
|
|
24305
24398
|
import { arch as arch2, platform as platform3 } from "os";
|
|
24306
24399
|
import { parse as parseYaml } from "yaml";
|
|
@@ -27194,7 +27287,7 @@ function shouldAutoInstallRuntimeMonitoringServices(env) {
|
|
|
27194
27287
|
|
|
27195
27288
|
// src/serverBackupArchive.ts
|
|
27196
27289
|
import { execFileSync as execFileSync3 } from "child_process";
|
|
27197
|
-
import { chmodSync as chmodSync3, lstatSync, readdirSync as readdirSync3, renameSync, rmSync as rmSync4 } from "fs";
|
|
27290
|
+
import { chmodSync as chmodSync3, lstatSync, readdirSync as readdirSync3, renameSync as renameSync2, rmSync as rmSync4 } from "fs";
|
|
27198
27291
|
import { randomUUID as randomUUID8 } from "crypto";
|
|
27199
27292
|
function assertRegularBackupTree(path2) {
|
|
27200
27293
|
const stat2 = lstatSync(path2);
|
|
@@ -27213,7 +27306,7 @@ function publishServerBackupArchive(sourceDir, archivePath, options = {}) {
|
|
|
27213
27306
|
try {
|
|
27214
27307
|
execFileSync3(options.tarCommand ?? "tar", ["-czf", temporaryArchivePath, "-C", sourceDir, "."], { stdio: "pipe" });
|
|
27215
27308
|
chmodSync3(temporaryArchivePath, 384);
|
|
27216
|
-
|
|
27309
|
+
renameSync2(temporaryArchivePath, archivePath);
|
|
27217
27310
|
chmodSync3(archivePath, 384);
|
|
27218
27311
|
} finally {
|
|
27219
27312
|
process.umask(previousUmask);
|
|
@@ -27815,7 +27908,7 @@ function signRuntimeWebhookPayload(payload, secret, timestamp, eventId) {
|
|
|
27815
27908
|
|
|
27816
27909
|
// src/serverUpdateState.ts
|
|
27817
27910
|
import { randomBytes as randomBytes7 } from "crypto";
|
|
27818
|
-
import { chmodSync as chmodSync4, closeSync, existsSync as existsSync8, mkdirSync as mkdirSync5, openSync, readFileSync as readFileSync6, renameSync as
|
|
27911
|
+
import { chmodSync as chmodSync4, closeSync, existsSync as existsSync8, mkdirSync as mkdirSync5, openSync, readFileSync as readFileSync6, renameSync as renameSync3, rmSync as rmSync5, writeFileSync as writeFileSync4 } from "fs";
|
|
27819
27912
|
import { dirname as dirname5, join as join6 } from "path";
|
|
27820
27913
|
function serverUpdateStatusFile(installPath, role) {
|
|
27821
27914
|
return join6(installPath, ".openmates", `${role}-update-status.json`);
|
|
@@ -27839,7 +27932,7 @@ function writeServerUpdateStatus(installPath, role, status) {
|
|
|
27839
27932
|
const temporaryPath = `${filePath}.${process.pid}.${randomBytes7(4).toString("hex")}.tmp`;
|
|
27840
27933
|
writeFileSync4(temporaryPath, `${JSON.stringify({ role, updated_at: (/* @__PURE__ */ new Date()).toISOString(), ...status }, null, 2)}
|
|
27841
27934
|
`, { mode: 384 });
|
|
27842
|
-
|
|
27935
|
+
renameSync3(temporaryPath, filePath);
|
|
27843
27936
|
chmodSync4(filePath, 384);
|
|
27844
27937
|
}
|
|
27845
27938
|
function acquireServerUpdateLock(installPath) {
|
|
@@ -48948,9 +49041,9 @@ function basenameFromUrl(url) {
|
|
|
48948
49041
|
return withoutQuery.split("/").pop()?.replace(/[^a-zA-Z0-9._-]/g, "_") ?? "";
|
|
48949
49042
|
}
|
|
48950
49043
|
function extensionFromUrl(url) {
|
|
48951
|
-
const
|
|
48952
|
-
const dotIndex =
|
|
48953
|
-
return dotIndex > 0 ?
|
|
49044
|
+
const basename5 = basenameFromUrl(url);
|
|
49045
|
+
const dotIndex = basename5.lastIndexOf(".");
|
|
49046
|
+
return dotIndex > 0 ? basename5.slice(dotIndex + 1).toLowerCase() : "";
|
|
48954
49047
|
}
|
|
48955
49048
|
function extensionFromLanguage(language) {
|
|
48956
49049
|
const normalized = language.toLowerCase();
|
|
@@ -74429,9 +74522,64 @@ function remoteErrorMessage(code) {
|
|
|
74429
74522
|
|
|
74430
74523
|
// src/selfUpdate.ts
|
|
74431
74524
|
import { spawnSync as spawnSync3 } from "child_process";
|
|
74432
|
-
import { readFileSync as readFileSync10 } from "fs";
|
|
74525
|
+
import { readFileSync as readFileSync10, mkdirSync as mkdirSync8, writeFileSync as writeFileSync8, renameSync as renameSync4 } from "fs";
|
|
74526
|
+
import { homedir as homedir8 } from "os";
|
|
74527
|
+
import { dirname as dirname8, basename as basename3, join as join10 } from "path";
|
|
74528
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
74433
74529
|
var PACKAGE_NAME = "openmates";
|
|
74434
|
-
|
|
74530
|
+
function channelFile() {
|
|
74531
|
+
return join10(homedir8(), ".openmates", "updates.json");
|
|
74532
|
+
}
|
|
74533
|
+
function parseChannel(value) {
|
|
74534
|
+
if (value === "dev") return "dev";
|
|
74535
|
+
if (value === "stable" || value === "main") return "stable";
|
|
74536
|
+
throw new Error("--channel must be dev, stable, or main (alias for stable)");
|
|
74537
|
+
}
|
|
74538
|
+
function savedChannel() {
|
|
74539
|
+
try {
|
|
74540
|
+
return parseChannel(JSON.parse(readFileSync10(channelFile(), "utf8")).channel);
|
|
74541
|
+
} catch (error) {
|
|
74542
|
+
if (error.code === "ENOENT") {
|
|
74543
|
+
return getCliPackageVersion().includes("-") ? "dev" : "stable";
|
|
74544
|
+
}
|
|
74545
|
+
throw error;
|
|
74546
|
+
}
|
|
74547
|
+
}
|
|
74548
|
+
function persistSelfUpdateChannel(plan) {
|
|
74549
|
+
if (plan.dryRun || !plan.persistChannel) return;
|
|
74550
|
+
const path2 = channelFile();
|
|
74551
|
+
mkdirSync8(dirname8(path2), { recursive: true, mode: 448 });
|
|
74552
|
+
const temporary = `${path2}.${process.pid}.tmp`;
|
|
74553
|
+
writeFileSync8(temporary, JSON.stringify({ channel: plan.channel }) + "\n", { mode: 384 });
|
|
74554
|
+
renameSync4(temporary, path2);
|
|
74555
|
+
}
|
|
74556
|
+
function installedNpmPrefix(moduleUrl = import.meta.url, platform4 = process.platform) {
|
|
74557
|
+
const packageRoot = dirname8(dirname8(fileURLToPath2(moduleUrl)));
|
|
74558
|
+
const modules = dirname8(packageRoot);
|
|
74559
|
+
if (basename3(packageRoot) !== PACKAGE_NAME || basename3(modules) !== "node_modules") return null;
|
|
74560
|
+
if (platform4 === "win32") return dirname8(modules);
|
|
74561
|
+
return basename3(dirname8(modules)) === "lib" ? dirname8(dirname8(modules)) : null;
|
|
74562
|
+
}
|
|
74563
|
+
function compareVersions(left, right) {
|
|
74564
|
+
const parse = (value) => {
|
|
74565
|
+
const match = /^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/.exec(value);
|
|
74566
|
+
if (!match) throw new Error(`Cannot compare CLI version '${value}'`);
|
|
74567
|
+
return { core: match.slice(1, 4).map(BigInt), pre: match[4]?.split(".") };
|
|
74568
|
+
};
|
|
74569
|
+
const a = parse(left), b = parse(right);
|
|
74570
|
+
for (let i = 0; i < 3; i++) if (a.core[i] !== b.core[i]) return a.core[i] > b.core[i] ? 1 : -1;
|
|
74571
|
+
if (!a.pre || !b.pre) return a.pre ? -1 : b.pre ? 1 : 0;
|
|
74572
|
+
for (let i = 0; i < Math.max(a.pre.length, b.pre.length); i++) {
|
|
74573
|
+
const x = a.pre[i], y = b.pre[i];
|
|
74574
|
+
if (x === y) continue;
|
|
74575
|
+
if (x === void 0 || y === void 0) return x === void 0 ? -1 : 1;
|
|
74576
|
+
const nx = /^\d+$/.test(x), ny = /^\d+$/.test(y);
|
|
74577
|
+
if (nx && ny) return BigInt(x) > BigInt(y) ? 1 : BigInt(x) < BigInt(y) ? -1 : 0;
|
|
74578
|
+
if (nx !== ny) return nx ? -1 : 1;
|
|
74579
|
+
return x > y ? 1 : -1;
|
|
74580
|
+
}
|
|
74581
|
+
return 0;
|
|
74582
|
+
}
|
|
74435
74583
|
var SAFE_TARGET_RE = /^[a-zA-Z0-9._@+~:-]+$/;
|
|
74436
74584
|
function getCliPackageVersion() {
|
|
74437
74585
|
try {
|
|
@@ -74443,10 +74591,14 @@ function getCliPackageVersion() {
|
|
|
74443
74591
|
}
|
|
74444
74592
|
function buildSelfUpdatePlan(flags) {
|
|
74445
74593
|
const packageManager = parsePackageManager(flags["package-manager"]);
|
|
74446
|
-
const
|
|
74594
|
+
const channel = flags.channel === void 0 ? savedChannel() : parseChannel(flags.channel);
|
|
74595
|
+
const target = parseTarget(flags.version ?? (channel === "dev" ? "alpha" : "latest"));
|
|
74447
74596
|
const packageSpec = `${PACKAGE_NAME}@${target}`;
|
|
74448
74597
|
const { command, args } = commandForPackageManager(packageManager, packageSpec);
|
|
74449
74598
|
return {
|
|
74599
|
+
channel,
|
|
74600
|
+
persistChannel: flags.channel !== void 0,
|
|
74601
|
+
allowDowngrade: flags["allow-downgrade"] === true,
|
|
74450
74602
|
packageManager,
|
|
74451
74603
|
command,
|
|
74452
74604
|
args,
|
|
@@ -74469,7 +74621,7 @@ function checkSelfUpdateStatus(plan) {
|
|
|
74469
74621
|
return {
|
|
74470
74622
|
currentVersion: plan.currentVersion,
|
|
74471
74623
|
latestVersion: latest.version,
|
|
74472
|
-
updateAvailable: plan.currentVersion
|
|
74624
|
+
updateAvailable: compareVersions(latest.version, plan.currentVersion) > 0 || plan.allowDowngrade && compareVersions(latest.version, plan.currentVersion) !== 0,
|
|
74473
74625
|
checkError: null
|
|
74474
74626
|
};
|
|
74475
74627
|
}
|
|
@@ -74499,7 +74651,8 @@ function resolveTargetVersion(target) {
|
|
|
74499
74651
|
}
|
|
74500
74652
|
const result = spawnSync3(commandName("npm"), ["view", `${PACKAGE_NAME}@${target}`, "version"], {
|
|
74501
74653
|
encoding: "utf-8",
|
|
74502
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
74654
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
74655
|
+
timeout: 3e4
|
|
74503
74656
|
});
|
|
74504
74657
|
if (result.error) return { version: null, error: result.error.message };
|
|
74505
74658
|
if (result.status !== 0) {
|
|
@@ -74515,7 +74668,7 @@ function parsePackageManager(value) {
|
|
|
74515
74668
|
throw new Error("--package-manager must be one of npm, pnpm, yarn, or bun");
|
|
74516
74669
|
}
|
|
74517
74670
|
function parseTarget(value) {
|
|
74518
|
-
if (value === void 0) return
|
|
74671
|
+
if (value === void 0) return "latest";
|
|
74519
74672
|
if (typeof value !== "string" || value.length === 0) {
|
|
74520
74673
|
throw new Error("--version requires a version or npm dist-tag");
|
|
74521
74674
|
}
|
|
@@ -74535,15 +74688,16 @@ function commandForPackageManager(packageManager, packageSpec) {
|
|
|
74535
74688
|
if (packageManager === "pnpm") return { command: commandName("pnpm"), args: ["add", "-g", packageSpec] };
|
|
74536
74689
|
if (packageManager === "yarn") return { command: commandName("yarn"), args: ["global", "add", packageSpec] };
|
|
74537
74690
|
if (packageManager === "bun") return { command: commandName("bun"), args: ["install", "-g", packageSpec] };
|
|
74538
|
-
|
|
74691
|
+
const prefix = installedNpmPrefix();
|
|
74692
|
+
return { command: commandName("npm"), args: ["install", "-g", packageSpec, ...prefix ? ["--prefix", prefix] : []] };
|
|
74539
74693
|
}
|
|
74540
74694
|
function commandName(name) {
|
|
74541
74695
|
return process.platform === "win32" ? `${name}.cmd` : name;
|
|
74542
74696
|
}
|
|
74543
74697
|
|
|
74544
74698
|
// src/workRecovery.ts
|
|
74545
|
-
import { mkdirSync as
|
|
74546
|
-
import { dirname as
|
|
74699
|
+
import { mkdirSync as mkdirSync9, renameSync as renameSync5, writeFileSync as writeFileSync9 } from "fs";
|
|
74700
|
+
import { dirname as dirname9 } from "path";
|
|
74547
74701
|
import { stringify } from "yaml";
|
|
74548
74702
|
async function projectPlanAssumption(plan, masterKey, assumption) {
|
|
74549
74703
|
const key = await planKeyFromRecord(plan.encrypted, masterKey);
|
|
@@ -74722,18 +74876,18 @@ function collectMismatchPaths(left, right, path2, mismatches) {
|
|
|
74722
74876
|
}
|
|
74723
74877
|
function writeWorkRecoveryAtomically(path2, document) {
|
|
74724
74878
|
validateWorkRecoveryDocument(document);
|
|
74725
|
-
|
|
74879
|
+
mkdirSync9(dirname9(path2), { recursive: true, mode: 448 });
|
|
74726
74880
|
const temporaryPath = `${path2}.tmp`;
|
|
74727
|
-
|
|
74728
|
-
|
|
74881
|
+
writeFileSync9(temporaryPath, stringify(document, { sortMapEntries: true, lineWidth: 0 }), { encoding: "utf8", mode: 384 });
|
|
74882
|
+
renameSync5(temporaryPath, path2);
|
|
74729
74883
|
}
|
|
74730
74884
|
|
|
74731
74885
|
// src/revolutBusinessCertificate.ts
|
|
74732
74886
|
import { execFileSync as execFileSync5 } from "child_process";
|
|
74733
74887
|
import { createSign, randomUUID as randomUUID14 } from "crypto";
|
|
74734
|
-
import { chmodSync as chmodSync7, existsSync as existsSync12, mkdirSync as
|
|
74735
|
-
import { homedir as
|
|
74736
|
-
import { join as
|
|
74888
|
+
import { chmodSync as chmodSync7, existsSync as existsSync12, mkdirSync as mkdirSync10, readFileSync as readFileSync11 } from "fs";
|
|
74889
|
+
import { homedir as homedir9 } from "os";
|
|
74890
|
+
import { join as join11, resolve as resolve10 } from "path";
|
|
74737
74891
|
var REVOLUT_BUSINESS_CERTIFICATE_DOCS_URL = "https://developer.revolut.com/docs/guides/manage-accounts/get-started/make-your-first-api-request#generate-a-private-and-a-public-certificate";
|
|
74738
74892
|
var REVOLUT_BUSINESS_DEFAULT_SANDBOX_REDIRECT_URI = "https://app.dev.openmates.org/oauth/revolut-business/callback";
|
|
74739
74893
|
var REVOLUT_BUSINESS_DEFAULT_PRODUCTION_REDIRECT_URI = "https://openmates.org/oauth/revolut-business/callback";
|
|
@@ -74743,7 +74897,7 @@ var REVOLUT_BUSINESS_AUDIENCE = "https://revolut.com";
|
|
|
74743
74897
|
var CERTIFICATE_DAYS = "1825";
|
|
74744
74898
|
var RSA_BITS = "2048";
|
|
74745
74899
|
function defaultRevolutBusinessCertificateDir(environment) {
|
|
74746
|
-
return
|
|
74900
|
+
return join11(homedir9(), ".openmates", "revolut-business", environment);
|
|
74747
74901
|
}
|
|
74748
74902
|
function defaultRevolutBusinessRedirectUri(environment) {
|
|
74749
74903
|
return environment === "sandbox" ? REVOLUT_BUSINESS_DEFAULT_SANDBOX_REDIRECT_URI : REVOLUT_BUSINESS_DEFAULT_PRODUCTION_REDIRECT_URI;
|
|
@@ -74766,7 +74920,7 @@ async function exchangeRevolutBusinessAuthorizationCode(options) {
|
|
|
74766
74920
|
if (!clientId) throw new Error("Missing Revolut Business client ID.");
|
|
74767
74921
|
const code = extractRevolutBusinessAuthorizationCode(options.codeOrRedirectUrl);
|
|
74768
74922
|
if (!code) throw new Error("Missing Revolut Business authorization code.");
|
|
74769
|
-
const privateKeyPem = options.privateKeyPem ?? readFileSync11(options.privateKeyPath ??
|
|
74923
|
+
const privateKeyPem = options.privateKeyPem ?? readFileSync11(options.privateKeyPath ?? join11(defaultRevolutBusinessCertificateDir(environment), "privatecert.pem"), "utf8");
|
|
74770
74924
|
const redirectUri = (options.redirectUri ?? defaultRevolutBusinessRedirectUri(environment)).trim();
|
|
74771
74925
|
const clientAssertion = generateRevolutBusinessClientAssertion({ clientId, privateKeyPem, redirectUri });
|
|
74772
74926
|
const response = await fetch(environment === "sandbox" ? "https://sandbox-b2b.revolut.com/api/1.0/auth/token" : "https://b2b.revolut.com/api/1.0/auth/token", {
|
|
@@ -74819,10 +74973,10 @@ function generateRevolutBusinessCertificate(options = {}) {
|
|
|
74819
74973
|
const redirectUri = (options.redirectUri ?? defaultRevolutBusinessRedirectUri(environment)).trim();
|
|
74820
74974
|
if (!title) throw new Error("Revolut certificate title must not be empty.");
|
|
74821
74975
|
if (!redirectUri.startsWith("https://")) throw new Error("Revolut OAuth redirect URI must start with https://.");
|
|
74822
|
-
|
|
74976
|
+
mkdirSync10(outputDir, { recursive: true, mode: 448 });
|
|
74823
74977
|
chmodSync7(outputDir, 448);
|
|
74824
|
-
const privateKeyPath =
|
|
74825
|
-
const publicCertificatePath =
|
|
74978
|
+
const privateKeyPath = join11(outputDir, "privatecert.pem");
|
|
74979
|
+
const publicCertificatePath = join11(outputDir, "publiccert.cer");
|
|
74826
74980
|
if (!options.overwrite && (existsSync12(privateKeyPath) || existsSync12(publicCertificatePath))) {
|
|
74827
74981
|
throw new Error(`Revolut certificate files already exist in ${outputDir}. Re-run with --overwrite to replace them.`);
|
|
74828
74982
|
}
|
|
@@ -74883,6 +75037,15 @@ async function main() {
|
|
|
74883
75037
|
assertTrustedAccountGuardEnvironment(parsed.flags);
|
|
74884
75038
|
assertTrustedAccountCommandAllowed(command);
|
|
74885
75039
|
}
|
|
75040
|
+
if (parsed.flags.profile !== void 0) {
|
|
75041
|
+
const profile = parsed.flags.profile;
|
|
75042
|
+
if (typeof profile !== "string" || !profile) throw new Error("--profile requires a profile name");
|
|
75043
|
+
resolveStateDir({ profile, stateDir: "" });
|
|
75044
|
+
if (process.env.OPENMATES_STATE_DIR?.trim()) {
|
|
75045
|
+
throw new Error("--profile cannot be combined with OPENMATES_STATE_DIR");
|
|
75046
|
+
}
|
|
75047
|
+
process.env.OPENMATES_PROFILE = profile;
|
|
75048
|
+
}
|
|
74886
75049
|
const client = OpenMatesClient.load({
|
|
74887
75050
|
apiUrl: typeof parsed.flags["api-url"] === "string" ? parsed.flags["api-url"] : void 0
|
|
74888
75051
|
});
|
|
@@ -75248,6 +75411,9 @@ function assertTrustedAccountCommandAllowed(command) {
|
|
|
75248
75411
|
}
|
|
75249
75412
|
}
|
|
75250
75413
|
function assertTrustedAccountGuardEnvironment(flags, environment = process.env) {
|
|
75414
|
+
if (flags.profile !== void 0 && flags.profile !== TRUST_GUARD_PROFILE) {
|
|
75415
|
+
throw new Error(`Trusted OpenCode CLI commands cannot override profile ${TRUST_GUARD_PROFILE}.`);
|
|
75416
|
+
}
|
|
75251
75417
|
if (environment.OPENMATES_PROFILE !== TRUST_GUARD_PROFILE) {
|
|
75252
75418
|
throw new Error(`Trusted OpenCode CLI commands require OPENMATES_PROFILE=${TRUST_GUARD_PROFILE}.`);
|
|
75253
75419
|
}
|
|
@@ -75287,11 +75453,14 @@ function handleSupport(flags) {
|
|
|
75287
75453
|
function handleSelfUpdate(command, flags) {
|
|
75288
75454
|
const plan = buildSelfUpdatePlan(flags);
|
|
75289
75455
|
const status = checkSelfUpdateStatus(plan);
|
|
75290
|
-
|
|
75456
|
+
if (status.checkError) throw new Error(`Update check failed: ${status.checkError}`);
|
|
75457
|
+
const shouldInstall = status.updateAvailable === true;
|
|
75291
75458
|
if (flags.json === true) {
|
|
75292
75459
|
if (!plan.dryRun && shouldInstall) runSelfUpdate(plan, { verbose: flags.verbose === true });
|
|
75460
|
+
persistSelfUpdateChannel(plan);
|
|
75293
75461
|
printJson2({
|
|
75294
75462
|
command,
|
|
75463
|
+
channel: plan.channel,
|
|
75295
75464
|
status: status.updateAvailable === false ? "up_to_date" : plan.dryRun ? "planned" : "success",
|
|
75296
75465
|
current_version: plan.currentVersion,
|
|
75297
75466
|
latest_version: status.latestVersion,
|
|
@@ -75308,6 +75477,7 @@ function handleSelfUpdate(command, flags) {
|
|
|
75308
75477
|
console.log("");
|
|
75309
75478
|
console.log("Checking for updates...");
|
|
75310
75479
|
console.log("");
|
|
75480
|
+
console.log(`Release channel: ${plan.channel}`);
|
|
75311
75481
|
console.log(`Current version: ${plan.currentVersion}`);
|
|
75312
75482
|
console.log(`Latest version: ${status.latestVersion ?? "unknown"}`);
|
|
75313
75483
|
if (status.checkError) {
|
|
@@ -75323,11 +75493,13 @@ function handleSelfUpdate(command, flags) {
|
|
|
75323
75493
|
return;
|
|
75324
75494
|
}
|
|
75325
75495
|
if (status.updateAvailable === false) {
|
|
75496
|
+
persistSelfUpdateChannel(plan);
|
|
75326
75497
|
console.log("OpenMates CLI is already up to date.");
|
|
75327
75498
|
return;
|
|
75328
75499
|
}
|
|
75329
75500
|
console.log(`Updating OpenMates CLI with ${plan.packageManager}...`);
|
|
75330
75501
|
runSelfUpdate(plan, { verbose: flags.verbose === true });
|
|
75502
|
+
persistSelfUpdateChannel(plan);
|
|
75331
75503
|
console.log(`Installed OpenMates CLI ${status.latestVersion ?? plan.target}.`);
|
|
75332
75504
|
console.log("");
|
|
75333
75505
|
console.log("OpenMates is up to date.");
|
|
@@ -75340,6 +75512,7 @@ function handleCliVersion(flags) {
|
|
|
75340
75512
|
if (flags.json === true) {
|
|
75341
75513
|
printJson2({
|
|
75342
75514
|
command: "version",
|
|
75515
|
+
channel: plan.channel,
|
|
75343
75516
|
current_version: status.currentVersion,
|
|
75344
75517
|
latest_version: status.latestVersion,
|
|
75345
75518
|
update_available: status.updateAvailable,
|
|
@@ -75349,6 +75522,7 @@ function handleCliVersion(flags) {
|
|
|
75349
75522
|
return;
|
|
75350
75523
|
}
|
|
75351
75524
|
console.log(`OpenMates CLI ${status.currentVersion}`);
|
|
75525
|
+
console.log(`Release channel: ${plan.channel}`);
|
|
75352
75526
|
if (status.checkError) {
|
|
75353
75527
|
console.log(`Update check failed: ${status.checkError}`);
|
|
75354
75528
|
return;
|
|
@@ -77740,7 +77914,7 @@ async function handleTeams(client, subcommand, rest, flags) {
|
|
|
77740
77914
|
if (action === "get") {
|
|
77741
77915
|
const output = requiredStringFlag(flags.output ?? flags.file ?? rest[2], "--output <path>");
|
|
77742
77916
|
const image = await client.getTeamProfileImage(teamId);
|
|
77743
|
-
|
|
77917
|
+
writeFileSync10(output, image.data, { mode: 384 });
|
|
77744
77918
|
if (flags.json === true) printJson2({ output, content_type: image.contentType, size_bytes: image.data.byteLength });
|
|
77745
77919
|
else console.log(`Team profile image written: ${output}`);
|
|
77746
77920
|
return;
|
|
@@ -77899,7 +78073,7 @@ async function handleTeams(client, subcommand, rest, flags) {
|
|
|
77899
78073
|
const output = requiredStringFlag(flags.output, "--output <path>");
|
|
77900
78074
|
const result = await client.exportTeamData(teamId);
|
|
77901
78075
|
const artifact = result.artifact && typeof result.artifact === "object" ? result.artifact : result;
|
|
77902
|
-
|
|
78076
|
+
writeFileSync10(output, `${JSON.stringify(artifact, null, 2)}
|
|
77903
78077
|
`, { encoding: "utf-8", mode: 384 });
|
|
77904
78078
|
if (flags.json === true) printJson2({ ...result, output });
|
|
77905
78079
|
else console.log(`Team export written: ${output}`);
|
|
@@ -78349,7 +78523,7 @@ async function resolveRemoteAccessBindings(client, masterKey, projects, candidat
|
|
|
78349
78523
|
const answer = (await promptLine2(`Create ${unresolved.length} missing Project${unresolved.length === 1 ? "" : "s"}? [y/N] `)).trim().toLowerCase();
|
|
78350
78524
|
if (answer !== "y" && answer !== "yes") throw new Error("Remote access Project creation cancelled.");
|
|
78351
78525
|
for (const rootPath of unresolved) {
|
|
78352
|
-
const project = await createEncryptedRemoteAccessProject(client, masterKey,
|
|
78526
|
+
const project = await createEncryptedRemoteAccessProject(client, masterKey, basename4(rootPath), context);
|
|
78353
78527
|
resolved.push({ rootPath, project, sourceId: randomUUID15() });
|
|
78354
78528
|
}
|
|
78355
78529
|
}
|
|
@@ -78361,7 +78535,7 @@ async function resolveRemoteAccessBindings(client, masterKey, projects, candidat
|
|
|
78361
78535
|
projectId: item.project.projectId,
|
|
78362
78536
|
rootPath: item.rootPath,
|
|
78363
78537
|
sourceType,
|
|
78364
|
-
displayName:
|
|
78538
|
+
displayName: basename4(item.rootPath)
|
|
78365
78539
|
});
|
|
78366
78540
|
const remoteSources = await client.listProjectSources(item.project.projectId, context);
|
|
78367
78541
|
const remoteSource = remoteSources.find((entry) => entry.source_id === source.sourceId);
|
|
@@ -79204,16 +79378,16 @@ ${deleted}/${resolved.length} chat(s) deleted.`);
|
|
|
79204
79378
|
}
|
|
79205
79379
|
}
|
|
79206
79380
|
const { mkdir: mkdir2, writeFile: writeFile2 } = await import("fs/promises");
|
|
79207
|
-
const { join:
|
|
79381
|
+
const { join: join12 } = await import("path");
|
|
79208
79382
|
if (useZip) {
|
|
79209
|
-
const tmpDir =
|
|
79383
|
+
const tmpDir = join12(outputDir, `.${filenameBase}_tmp`);
|
|
79210
79384
|
await mkdir2(tmpDir, { recursive: true });
|
|
79211
|
-
await writeFile2(
|
|
79212
|
-
await writeFile2(
|
|
79385
|
+
await writeFile2(join12(tmpDir, `${filenameBase}.yml`), yamlContent);
|
|
79386
|
+
await writeFile2(join12(tmpDir, `${filenameBase}.md`), mdContent);
|
|
79213
79387
|
if (codeEmbeds.length > 0) {
|
|
79214
79388
|
for (const ce of codeEmbeds) {
|
|
79215
79389
|
const fpath = ce.filePath ?? ce.filename ?? `${ce.embedId.slice(0, 8)}.${getExtForLang(ce.language)}`;
|
|
79216
|
-
const fullPath =
|
|
79390
|
+
const fullPath = join12(tmpDir, "code", fpath);
|
|
79217
79391
|
await mkdir2(fullPath.substring(0, fullPath.lastIndexOf("/")), {
|
|
79218
79392
|
recursive: true
|
|
79219
79393
|
});
|
|
@@ -79221,13 +79395,13 @@ ${deleted}/${resolved.length} chat(s) deleted.`);
|
|
|
79221
79395
|
}
|
|
79222
79396
|
}
|
|
79223
79397
|
if (transcriptEmbeds.length > 0) {
|
|
79224
|
-
const tDir =
|
|
79398
|
+
const tDir = join12(tmpDir, "transcripts");
|
|
79225
79399
|
await mkdir2(tDir, { recursive: true });
|
|
79226
79400
|
for (const te of transcriptEmbeds) {
|
|
79227
|
-
await writeFile2(
|
|
79401
|
+
await writeFile2(join12(tDir, te.filename), te.content);
|
|
79228
79402
|
}
|
|
79229
79403
|
}
|
|
79230
|
-
const zipPath =
|
|
79404
|
+
const zipPath = join12(outputDir, `${filenameBase}.zip`);
|
|
79231
79405
|
const { execSync: execSync2 } = await import("child_process");
|
|
79232
79406
|
try {
|
|
79233
79407
|
execSync2(`cd "${tmpDir}" && zip -r "${zipPath}" .`, { stdio: "pipe" });
|
|
@@ -79242,17 +79416,17 @@ ${deleted}/${resolved.length} chat(s) deleted.`);
|
|
|
79242
79416
|
);
|
|
79243
79417
|
}
|
|
79244
79418
|
} else {
|
|
79245
|
-
const chatDir =
|
|
79419
|
+
const chatDir = join12(outputDir, filenameBase);
|
|
79246
79420
|
await mkdir2(chatDir, { recursive: true });
|
|
79247
79421
|
const written = [];
|
|
79248
|
-
await writeFile2(
|
|
79422
|
+
await writeFile2(join12(chatDir, `${filenameBase}.yml`), yamlContent);
|
|
79249
79423
|
written.push(`${filenameBase}.yml`);
|
|
79250
|
-
await writeFile2(
|
|
79424
|
+
await writeFile2(join12(chatDir, `${filenameBase}.md`), mdContent);
|
|
79251
79425
|
written.push(`${filenameBase}.md`);
|
|
79252
79426
|
if (codeEmbeds.length > 0) {
|
|
79253
79427
|
for (const ce of codeEmbeds) {
|
|
79254
79428
|
const fpath = ce.filePath ?? ce.filename ?? `${ce.embedId.slice(0, 8)}.${getExtForLang(ce.language)}`;
|
|
79255
|
-
const fullPath =
|
|
79429
|
+
const fullPath = join12(chatDir, "code", fpath);
|
|
79256
79430
|
await mkdir2(fullPath.substring(0, fullPath.lastIndexOf("/")), {
|
|
79257
79431
|
recursive: true
|
|
79258
79432
|
});
|
|
@@ -79261,10 +79435,10 @@ ${deleted}/${resolved.length} chat(s) deleted.`);
|
|
|
79261
79435
|
}
|
|
79262
79436
|
}
|
|
79263
79437
|
if (transcriptEmbeds.length > 0) {
|
|
79264
|
-
const tDir =
|
|
79438
|
+
const tDir = join12(chatDir, "transcripts");
|
|
79265
79439
|
await mkdir2(tDir, { recursive: true });
|
|
79266
79440
|
for (const te of transcriptEmbeds) {
|
|
79267
|
-
await writeFile2(
|
|
79441
|
+
await writeFile2(join12(tDir, te.filename), te.content);
|
|
79268
79442
|
written.push(`transcripts/${te.filename}`);
|
|
79269
79443
|
}
|
|
79270
79444
|
}
|
|
@@ -79300,7 +79474,7 @@ ${deleted}/${resolved.length} chat(s) deleted.`);
|
|
|
79300
79474
|
printJson2({
|
|
79301
79475
|
chat_id: chat.id,
|
|
79302
79476
|
title: chat.title,
|
|
79303
|
-
output_dir: useZip ?
|
|
79477
|
+
output_dir: useZip ? join12(outputDir, `${filenameBase}.zip`) : join12(outputDir, filenameBase),
|
|
79304
79478
|
files,
|
|
79305
79479
|
code_embeds: codeEmbeds.length,
|
|
79306
79480
|
transcript_embeds: transcriptEmbeds.length
|
|
@@ -80326,7 +80500,7 @@ function buildImagesAiDetectionSummary(uploadResult, filePath) {
|
|
|
80326
80500
|
const classification = classifyImagesAiDetection(score);
|
|
80327
80501
|
return {
|
|
80328
80502
|
file: filePath,
|
|
80329
|
-
filename: uploadResult.filename ||
|
|
80503
|
+
filename: uploadResult.filename || basename4(filePath),
|
|
80330
80504
|
content_type: uploadResult.content_type,
|
|
80331
80505
|
embed_id: uploadResult.embed_id,
|
|
80332
80506
|
deduplicated: uploadResult.deduplicated,
|
|
@@ -81357,7 +81531,7 @@ async function handleEmbeds(client, subcommand, rest, flags) {
|
|
|
81357
81531
|
throw new Error("Embed version content was not available after local reconstruction.");
|
|
81358
81532
|
}
|
|
81359
81533
|
if (typeof flags.output === "string") {
|
|
81360
|
-
|
|
81534
|
+
writeFileSync10(flags.output, result.content, "utf-8");
|
|
81361
81535
|
if (flags.json === true) {
|
|
81362
81536
|
printJson2({ ...result, output: flags.output });
|
|
81363
81537
|
} else {
|
|
@@ -81641,12 +81815,12 @@ async function parseAccountImportFile(parserFormat, file, flags = {}) {
|
|
|
81641
81815
|
const selectedSource = requestedSource;
|
|
81642
81816
|
if (parserFormat === "generic") {
|
|
81643
81817
|
if (selectedSource !== "gemini" && selectedSource !== "other") throw new Error("Generic account import requires --source gemini or --source other.");
|
|
81644
|
-
return parseGenericImportBuffer(payload,
|
|
81818
|
+
return parseGenericImportBuffer(payload, basename4(file), selectedSource);
|
|
81645
81819
|
}
|
|
81646
|
-
if (parserFormat === "claude") return parseClaudeImportBuffer(payload,
|
|
81647
|
-
if (parserFormat === "chatgpt") return parseChatGPTImportBuffer(payload,
|
|
81648
|
-
if (parserFormat === "opencode") return parseOpenCodeImportBuffer(payload,
|
|
81649
|
-
return parseOpenMatesImportBuffer(payload,
|
|
81820
|
+
if (parserFormat === "claude") return parseClaudeImportBuffer(payload, basename4(file), selectedSource);
|
|
81821
|
+
if (parserFormat === "chatgpt") return parseChatGPTImportBuffer(payload, basename4(file), selectedSource);
|
|
81822
|
+
if (parserFormat === "opencode") return parseOpenCodeImportBuffer(payload, basename4(file), selectedSource);
|
|
81823
|
+
return parseOpenMatesImportBuffer(payload, basename4(file), typeof flags.password === "string" ? flags.password : void 0, selectedSource);
|
|
81650
81824
|
}
|
|
81651
81825
|
async function runAccountImport(client, parserFormat, file, flags) {
|
|
81652
81826
|
if (parserFormat === "generic" && typeof flags.source !== "string") throw new Error("Generic account import requires --source gemini or --source other.");
|
|
@@ -82016,11 +82190,11 @@ function parseYamlScalar(value) {
|
|
|
82016
82190
|
}
|
|
82017
82191
|
async function saveDownloadedDocument(document, output) {
|
|
82018
82192
|
const { mkdir: mkdir2, writeFile: writeFile2 } = await import("fs/promises");
|
|
82019
|
-
const { join:
|
|
82193
|
+
const { join: join12, basename: basename5, dirname: dirname11 } = await import("path");
|
|
82020
82194
|
const target = typeof output === "string" ? output : ".";
|
|
82021
|
-
const filename =
|
|
82022
|
-
const filePath = target.endsWith(".pdf") ? target :
|
|
82023
|
-
await mkdir2(
|
|
82195
|
+
const filename = basename5(document.filename || "document.pdf");
|
|
82196
|
+
const filePath = target.endsWith(".pdf") ? target : join12(target, filename);
|
|
82197
|
+
await mkdir2(dirname11(filePath), { recursive: true });
|
|
82024
82198
|
await writeFile2(filePath, document.data);
|
|
82025
82199
|
return filePath;
|
|
82026
82200
|
}
|
|
@@ -82192,7 +82366,7 @@ async function handleFinance(client, subcommand, _rest, flags) {
|
|
|
82192
82366
|
}
|
|
82193
82367
|
function readFinanceCsvStatements(flags) {
|
|
82194
82368
|
const paths = parseCsvFlag(flags.csv) ?? [];
|
|
82195
|
-
return paths.map((filePath) => ({ filename:
|
|
82369
|
+
return paths.map((filePath) => ({ filename: basename4(filePath), content: readFileSync12(filePath, "utf8") }));
|
|
82196
82370
|
}
|
|
82197
82371
|
function buildFinanceCheckAccountsInput(flags, csvStatements, connectedAccount) {
|
|
82198
82372
|
const input = {
|
|
@@ -82487,7 +82661,7 @@ async function promptPlainText(question) {
|
|
|
82487
82661
|
}
|
|
82488
82662
|
async function writeSecretFile(filePath, content, force = false) {
|
|
82489
82663
|
const { mkdir: mkdir2, writeFile: writeFile2, stat: stat2 } = await import("fs/promises");
|
|
82490
|
-
const { dirname:
|
|
82664
|
+
const { dirname: dirname11 } = await import("path");
|
|
82491
82665
|
try {
|
|
82492
82666
|
await stat2(filePath);
|
|
82493
82667
|
if (!force) throw new Error(`${filePath} already exists. Use --force to overwrite.`);
|
|
@@ -82497,7 +82671,7 @@ async function writeSecretFile(filePath, content, force = false) {
|
|
|
82497
82671
|
}
|
|
82498
82672
|
if (error instanceof Error && !("code" in error)) throw error;
|
|
82499
82673
|
}
|
|
82500
|
-
await mkdir2(
|
|
82674
|
+
await mkdir2(dirname11(filePath), { recursive: true });
|
|
82501
82675
|
await writeFile2(filePath, content, { mode: 384 });
|
|
82502
82676
|
return filePath;
|
|
82503
82677
|
}
|
|
@@ -85642,6 +85816,7 @@ Commands:
|
|
|
85642
85816
|
|
|
85643
85817
|
Flags:
|
|
85644
85818
|
--json Output raw JSON instead of formatted output
|
|
85819
|
+
--profile <name> Use an isolated login profile (also OPENMATES_PROFILE)
|
|
85645
85820
|
--api-url <url> Override API base URL (default: installed self-host server, then https://api.openmates.org)
|
|
85646
85821
|
--api-key <key> Optional API key override (or set OPENMATES_API_KEY)
|
|
85647
85822
|
--version Show CLI version and update availability
|
|
@@ -85663,12 +85838,16 @@ function printSelfUpdateHelp() {
|
|
|
85663
85838
|
openmates update [--version <version|tag>] [--package-manager <name>] [--dry-run] [--verbose] [--json]
|
|
85664
85839
|
openmates upgrade [--version <version|tag>] [--package-manager <name>] [--dry-run] [--verbose] [--json]
|
|
85665
85840
|
|
|
85666
|
-
Updates the globally installed openmates package
|
|
85841
|
+
Updates the globally installed openmates package using the saved release channel.
|
|
85842
|
+
Stable installations default to stable; prereleases default to dev.
|
|
85843
|
+
Channel changes persist only after a successful update or up-to-date check.
|
|
85667
85844
|
|
|
85668
85845
|
Options:
|
|
85669
|
-
--version <version|tag> Install a specific npm version or dist-tag (
|
|
85846
|
+
--version <version|tag> Install a specific npm version or dist-tag (one-time override)
|
|
85670
85847
|
--package-manager <name> npm, pnpm, yarn, or bun (default: detect, then npm)
|
|
85671
85848
|
--dry-run Print the package-manager command without running it
|
|
85849
|
+
--channel <dev|stable|main> Save release channel (dev uses npm alpha; stable/main uses latest)
|
|
85850
|
+
--allow-downgrade Explicitly allow installing an older version
|
|
85672
85851
|
--verbose Stream package-manager output during installation
|
|
85673
85852
|
--json Output the update plan/result as JSON`);
|
|
85674
85853
|
}
|
|
@@ -86475,7 +86654,7 @@ async function handleDocs(client, subcommand, rest, flags) {
|
|
|
86475
86654
|
}
|
|
86476
86655
|
if (subcommand === "download") {
|
|
86477
86656
|
const { writeFile: writeFile2, mkdir: mkdir2 } = await import("fs/promises");
|
|
86478
|
-
const { join:
|
|
86657
|
+
const { join: join12, dirname: dirname11 } = await import("path");
|
|
86479
86658
|
if (flags.all === true) {
|
|
86480
86659
|
const outputDir = typeof flags.output === "string" ? flags.output : "./openmates-docs";
|
|
86481
86660
|
const tree = await client.listDocs();
|
|
@@ -86484,8 +86663,8 @@ async function handleDocs(client, subcommand, rest, flags) {
|
|
|
86484
86663
|
let count = 0;
|
|
86485
86664
|
for (const slug2 of slugs) {
|
|
86486
86665
|
const content2 = await client.getDoc(slug2);
|
|
86487
|
-
const filePath =
|
|
86488
|
-
await mkdir2(
|
|
86666
|
+
const filePath = join12(outputDir, `${slug2}.md`);
|
|
86667
|
+
await mkdir2(dirname11(filePath), { recursive: true });
|
|
86489
86668
|
await writeFile2(filePath, content2, "utf-8");
|
|
86490
86669
|
count++;
|
|
86491
86670
|
process.stderr.write(`\r Downloaded ${count}/${slugs.length}`);
|
|
@@ -86557,8 +86736,8 @@ function isCliEntrypoint() {
|
|
|
86557
86736
|
if (!entrypoint) return false;
|
|
86558
86737
|
try {
|
|
86559
86738
|
const invokedPath = realpathSync2(entrypoint);
|
|
86560
|
-
const modulePath = realpathSync2(
|
|
86561
|
-
return invokedPath === modulePath ||
|
|
86739
|
+
const modulePath = realpathSync2(fileURLToPath3(import.meta.url));
|
|
86740
|
+
return invokedPath === modulePath || basename4(invokedPath) === "cli.js" && dirname10(invokedPath) === dirname10(modulePath);
|
|
86562
86741
|
} catch {
|
|
86563
86742
|
return false;
|
|
86564
86743
|
}
|
|
@@ -1734,6 +1734,7 @@ declare class OpenMatesClient {
|
|
|
1734
1734
|
readonly apiUrl: string;
|
|
1735
1735
|
private session;
|
|
1736
1736
|
private readonly http;
|
|
1737
|
+
private readonly explicitSession;
|
|
1737
1738
|
constructor(options?: OpenMatesClientOptions);
|
|
1738
1739
|
static load(options?: OpenMatesClientOptions): OpenMatesClient;
|
|
1739
1740
|
hasSession(): boolean;
|
|
@@ -2741,6 +2742,8 @@ declare class OpenMatesClient {
|
|
|
2741
2742
|
private downloadPaymentPdf;
|
|
2742
2743
|
private ensureEmailEncryptionKey;
|
|
2743
2744
|
private hydrateEmailEncryptionKey;
|
|
2745
|
+
private withFreshStoredSession;
|
|
2746
|
+
private loginRecoveryCommand;
|
|
2744
2747
|
private requireSession;
|
|
2745
2748
|
getMasterKeyBytes(): Uint8Array;
|
|
2746
2749
|
private decryptTopicPreferences;
|
package/dist/cli.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
export { aa as ImagesAiDetectionClassification, ab as ImagesAiDetectionSummary, aA as assertTrustedAccountCommandAllowed, aB as assertTrustedAccountGuardEnvironment, as as buildImagesAiDetectionSummary, aC as buildTravelConnectionsRequest, at as classifyImagesAiDetection, av as formatImagesAiDetectionLabel, aw as getExtForLang, aD as requireExactConfirmation, aE as resolveProjectContext, az as serializeToYaml, aF as shouldRequireTrustedAccountGuard } from './cli-
|
|
2
|
+
export { aa as ImagesAiDetectionClassification, ab as ImagesAiDetectionSummary, aA as assertTrustedAccountCommandAllowed, aB as assertTrustedAccountGuardEnvironment, as as buildImagesAiDetectionSummary, aC as buildTravelConnectionsRequest, at as classifyImagesAiDetection, av as formatImagesAiDetectionLabel, aw as getExtForLang, aD as requireExactConfirmation, aE as resolveProjectContext, az as serializeToYaml, aF as shouldRequireTrustedAccountGuard } from './cli-BLFXUeuE.js';
|
package/dist/cli.js
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { U as UserTaskStatus, a as UserTaskAssigneeType, b as UserTaskAssigneeIdentity, c as UserTaskRecord, d as UserTaskActivityRecord, e as UserPlanStatus, f as UserPlanRecord, g as UserPlanVerificationStatus, h as UserPlanLearningType, i as UserPlanLearningTargetKind, j as UserPlanLearningStatus, k as UserPlanLearningLevel, l as UserPlanLearningRecord, m as UserPlanCriterionRecord, n as UserPlanVerificationRecord, o as UserPlanCreateInput, p as UserPlanUpdateInput, P as ProjectItemRecord, q as UserPlanLearningCreateTasksInput, r as UserPlanLearningCreateTasksResult, s as UserTaskReorderInput, W as WorkflowSummary, t as WorkflowCapability, u as WorkflowDetail, v as WorkflowInputStartParams, w as WorkflowInputSessionResult, x as WorkflowInputSessionDetail, y as WorkflowInputEvent, z as WorkflowGraph, A as WorkflowRunContentRetention, B as WorkflowRunDetail, C as WorkflowRunCancellationResult, D as WorkflowTemplateProjectionUpsertParams, E as WorkflowTemplateProjectionResult, F as PublicWorkflowTemplateProjection, G as WorkflowTemplateProjectionRevocationResult, H as WorkflowTemplateBindingCompletionParams, I as WorkflowTemplateBindingCompletionResult, J as WorkflowTemplateShortUrlParams, K as WorkflowTemplateShortUrlResult, S as ShortUrlRevokeResult, L as WorkflowTemplateImportPayload, M as ImportedWorkflowTemplate } from './cli-
|
|
2
|
-
export { N as AuthMethodsStatus, O as AuthoritativeChatReconciliation, Q as BackupCodesResult, R as BankTransferOrderDetails, T as BankTransferStatus, V as CachedChat, X as CachedNewChatSuggestion, Y as ChatListPage, Z as CliSignupResult, _ as DecryptedDraft, $ as DecryptedEmbed, a0 as DecryptedMemoryEntry, a1 as DecryptedMessage, a2 as DecryptedNewChatSuggestion, a3 as DocsFile, a4 as DocsFolder, a5 as DocsSearchResult, a6 as DocsTree, a7 as EncryptedDraft, a8 as GiftCardBankTransferStatus, a9 as INTEREST_TAG_IDS, aa as ImagesAiDetectionClassification, ab as ImagesAiDetectionSummary, ac as InterestTagId, ad as MATE_NAMES, ae as MEMORY_TYPE_REGISTRY, af as MemoryFieldDef, ag as MemoryTypeDef, ah as OpenMatesClient, ai as OpenMatesClientOptions, aj as OpenMatesSession, ak as SyncCache, al as TopicPreferencesPayload, am as TotpSetupStartResult, an as WorkflowEdge, ao as WorkflowNode, ap as WorkflowNodeRun, aq as WorkflowNodeType, ar as WorkflowRunContentStorage, as as buildImagesAiDetectionSummary, at as classifyImagesAiDetection, au as deriveAppUrl, av as formatImagesAiDetectionLabel, aw as getExtForLang, ax as normalizeInterestTagIds, ay as reconcileAuthoritativeChats, az as serializeToYaml } from './cli-
|
|
1
|
+
import { U as UserTaskStatus, a as UserTaskAssigneeType, b as UserTaskAssigneeIdentity, c as UserTaskRecord, d as UserTaskActivityRecord, e as UserPlanStatus, f as UserPlanRecord, g as UserPlanVerificationStatus, h as UserPlanLearningType, i as UserPlanLearningTargetKind, j as UserPlanLearningStatus, k as UserPlanLearningLevel, l as UserPlanLearningRecord, m as UserPlanCriterionRecord, n as UserPlanVerificationRecord, o as UserPlanCreateInput, p as UserPlanUpdateInput, P as ProjectItemRecord, q as UserPlanLearningCreateTasksInput, r as UserPlanLearningCreateTasksResult, s as UserTaskReorderInput, W as WorkflowSummary, t as WorkflowCapability, u as WorkflowDetail, v as WorkflowInputStartParams, w as WorkflowInputSessionResult, x as WorkflowInputSessionDetail, y as WorkflowInputEvent, z as WorkflowGraph, A as WorkflowRunContentRetention, B as WorkflowRunDetail, C as WorkflowRunCancellationResult, D as WorkflowTemplateProjectionUpsertParams, E as WorkflowTemplateProjectionResult, F as PublicWorkflowTemplateProjection, G as WorkflowTemplateProjectionRevocationResult, H as WorkflowTemplateBindingCompletionParams, I as WorkflowTemplateBindingCompletionResult, J as WorkflowTemplateShortUrlParams, K as WorkflowTemplateShortUrlResult, S as ShortUrlRevokeResult, L as WorkflowTemplateImportPayload, M as ImportedWorkflowTemplate } from './cli-BLFXUeuE.js';
|
|
2
|
+
export { N as AuthMethodsStatus, O as AuthoritativeChatReconciliation, Q as BackupCodesResult, R as BankTransferOrderDetails, T as BankTransferStatus, V as CachedChat, X as CachedNewChatSuggestion, Y as ChatListPage, Z as CliSignupResult, _ as DecryptedDraft, $ as DecryptedEmbed, a0 as DecryptedMemoryEntry, a1 as DecryptedMessage, a2 as DecryptedNewChatSuggestion, a3 as DocsFile, a4 as DocsFolder, a5 as DocsSearchResult, a6 as DocsTree, a7 as EncryptedDraft, a8 as GiftCardBankTransferStatus, a9 as INTEREST_TAG_IDS, aa as ImagesAiDetectionClassification, ab as ImagesAiDetectionSummary, ac as InterestTagId, ad as MATE_NAMES, ae as MEMORY_TYPE_REGISTRY, af as MemoryFieldDef, ag as MemoryTypeDef, ah as OpenMatesClient, ai as OpenMatesClientOptions, aj as OpenMatesSession, ak as SyncCache, al as TopicPreferencesPayload, am as TotpSetupStartResult, an as WorkflowEdge, ao as WorkflowNode, ap as WorkflowNodeRun, aq as WorkflowNodeType, ar as WorkflowRunContentStorage, as as buildImagesAiDetectionSummary, at as classifyImagesAiDetection, au as deriveAppUrl, av as formatImagesAiDetectionLabel, aw as getExtForLang, ax as normalizeInterestTagIds, ay as reconcileAuthoritativeChats, az as serializeToYaml } from './cli-BLFXUeuE.js';
|
|
3
3
|
|
|
4
4
|
interface ProjectedAssistantSpeechSegment {
|
|
5
5
|
sequence: number;
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openmates",
|
|
3
|
-
"version": "0.18.0-alpha.
|
|
3
|
+
"version": "0.18.0-alpha.4",
|
|
4
4
|
"description": "OpenMates CLI and SDK",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -73,6 +73,7 @@
|
|
|
73
73
|
"@toon-format/toon": "2.3.1",
|
|
74
74
|
"ahocorasick": "1.0.2",
|
|
75
75
|
"jszip": "^3.10.1",
|
|
76
|
+
"proper-lockfile": "^4.1.2",
|
|
76
77
|
"qrcode-terminal": "^0.12.0",
|
|
77
78
|
"tweetnacl": "^1.0.3",
|
|
78
79
|
"ws": "8.21.0",
|
|
@@ -81,6 +82,7 @@
|
|
|
81
82
|
"devDependencies": {
|
|
82
83
|
"@repo/eslint-config": "workspace:*",
|
|
83
84
|
"@types/node": "^24.5.0",
|
|
85
|
+
"@types/proper-lockfile": "^4.1.4",
|
|
84
86
|
"@types/qrcode-terminal": "^0.12.2",
|
|
85
87
|
"@types/ws": "^8.18.1",
|
|
86
88
|
"eslint": "^9.35.0",
|