openmates 0.18.0-alpha.1 → 0.18.0-alpha.3
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-RLOO6QKC.js → chunk-65ZA6VF2.js} +268 -160
- package/dist/cli.js +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
|
@@ -20131,12 +20131,12 @@ var ACCOUNT_EXPORT_FORBIDDEN_VALUE_PATTERNS = [
|
|
|
20131
20131
|
];
|
|
20132
20132
|
async function writeAccountExportArchive(bundle, flags = {}) {
|
|
20133
20133
|
const { mkdir: mkdir2, writeFile: writeFile2 } = await import("fs/promises");
|
|
20134
|
-
const { join:
|
|
20134
|
+
const { join: join12, dirname: dirname11 } = await import("path");
|
|
20135
20135
|
const exportId = safeArchiveSegment(String(bundle.export.export_id ?? `export-${Date.now()}`));
|
|
20136
20136
|
const archiveFormat = flags.format === "directory" ? "directory" : "zip";
|
|
20137
20137
|
const password = typeof flags.password === "string" && flags.password.length > 0 ? flags.password : null;
|
|
20138
20138
|
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 :
|
|
20139
|
+
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
20140
|
const zip = archiveFormat === "zip" ? new JSZip3() : null;
|
|
20141
20141
|
const writtenFiles = [];
|
|
20142
20142
|
async function writeArchiveText(relativePath, content) {
|
|
@@ -20147,8 +20147,8 @@ async function writeAccountExportArchive(bundle, flags = {}) {
|
|
|
20147
20147
|
return;
|
|
20148
20148
|
}
|
|
20149
20149
|
const stagingDir = outputPath;
|
|
20150
|
-
const fullPath =
|
|
20151
|
-
await mkdir2(
|
|
20150
|
+
const fullPath = join12(stagingDir, relativePath);
|
|
20151
|
+
await mkdir2(dirname11(fullPath), { recursive: true });
|
|
20152
20152
|
await writeFile2(fullPath, content, "utf-8");
|
|
20153
20153
|
writtenFiles.push(relativePath);
|
|
20154
20154
|
}
|
|
@@ -20165,7 +20165,7 @@ async function writeAccountExportArchive(bundle, flags = {}) {
|
|
|
20165
20165
|
}
|
|
20166
20166
|
await writeAccountExportChatFiles(domainPayloads.chats ?? [], writeArchiveText);
|
|
20167
20167
|
if (archiveFormat === "directory") return { output: outputPath, format: "directory", files: writtenFiles.length };
|
|
20168
|
-
await mkdir2(
|
|
20168
|
+
await mkdir2(dirname11(outputPath), { recursive: true });
|
|
20169
20169
|
const zipBuffer = await zip.generateAsync({ type: "nodebuffer", compression: "DEFLATE" });
|
|
20170
20170
|
await writeFile2(outputPath, password ? encryptZipBuffer(zipBuffer, password) : zipBuffer);
|
|
20171
20171
|
return { output: outputPath, format: "zip", files: writtenFiles.length, ...password ? { encrypted: true } : {} };
|
|
@@ -24298,10 +24298,10 @@ var OpenMatesBenchmark = class {
|
|
|
24298
24298
|
// src/cli.ts
|
|
24299
24299
|
import { createInterface as createInterface5 } from "readline/promises";
|
|
24300
24300
|
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
|
|
24304
|
-
import { createHash as createHash14, randomBytes as randomBytes9, randomUUID as
|
|
24301
|
+
import { existsSync as existsSync13, readFileSync as readFileSync12, realpathSync as realpathSync2, writeFileSync as writeFileSync10 } from "fs";
|
|
24302
|
+
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
24303
|
+
import { basename as basename4, dirname as dirname10 } from "path";
|
|
24304
|
+
import { createHash as createHash14, randomBytes as randomBytes9, randomUUID as randomUUID15 } from "crypto";
|
|
24305
24305
|
import { arch as arch2, platform as platform3 } from "os";
|
|
24306
24306
|
import { parse as parseYaml } from "yaml";
|
|
24307
24307
|
import WebSocket2 from "ws";
|
|
@@ -26479,9 +26479,9 @@ function formatTs(ts) {
|
|
|
26479
26479
|
}
|
|
26480
26480
|
|
|
26481
26481
|
// src/server.ts
|
|
26482
|
-
import { execFileSync as
|
|
26483
|
-
import { createHash as createHash12, randomBytes as randomBytes8, randomUUID as
|
|
26484
|
-
import { appendFileSync, chmodSync as
|
|
26482
|
+
import { execFileSync as execFileSync4, execSync, spawn as nodeSpawn, spawnSync } from "child_process";
|
|
26483
|
+
import { createHash as createHash12, randomBytes as randomBytes8, randomUUID as randomUUID11 } from "crypto";
|
|
26484
|
+
import { appendFileSync, chmodSync as chmodSync5, closeSync as closeSync2, copyFileSync as copyFileSync2, cpSync, existsSync as existsSync9, mkdirSync as mkdirSync6, mkdtempSync, openSync as openSync2, readFileSync as readFileSync7, readSync, readdirSync as readdirSync4, rmSync as rmSync6, writeFileSync as writeFileSync5 } from "fs";
|
|
26485
26485
|
import { createInterface as createInterface3 } from "readline";
|
|
26486
26486
|
import { createInterface as createPromptInterface } from "readline/promises";
|
|
26487
26487
|
import { homedir as homedir6 } from "os";
|
|
@@ -26955,12 +26955,11 @@ function planUpdate(input) {
|
|
|
26955
26955
|
function planBackup(input) {
|
|
26956
26956
|
const role = parseServerRole(input.role);
|
|
26957
26957
|
const contentsByRole = {
|
|
26958
|
-
core: ["postgres-dump", "
|
|
26959
|
-
upload: ["
|
|
26960
|
-
preview: ["runtime-env", "runtime-config", "
|
|
26958
|
+
core: ["postgres-dump", "runtime-env", "runtime-config", "manifest", "checksums"],
|
|
26959
|
+
upload: ["runtime-env", "runtime-config", "manifest", "checksums"],
|
|
26960
|
+
preview: ["runtime-env", "runtime-config", "manifest", "checksums"]
|
|
26961
26961
|
};
|
|
26962
26962
|
const contents = [...contentsByRole[role]];
|
|
26963
|
-
if (input.includeObservability) contents.push("openobserve-data", "prometheus-data");
|
|
26964
26963
|
return { role, contents, fileMode: 384 };
|
|
26965
26964
|
}
|
|
26966
26965
|
function planRestore(input) {
|
|
@@ -27193,9 +27192,38 @@ function shouldAutoInstallRuntimeMonitoringServices(env) {
|
|
|
27193
27192
|
return env.OPENMATES_SKIP_RUNTIME_MONITORING !== "1";
|
|
27194
27193
|
}
|
|
27195
27194
|
|
|
27195
|
+
// src/serverBackupArchive.ts
|
|
27196
|
+
import { execFileSync as execFileSync3 } from "child_process";
|
|
27197
|
+
import { chmodSync as chmodSync3, lstatSync, readdirSync as readdirSync3, renameSync, rmSync as rmSync4 } from "fs";
|
|
27198
|
+
import { randomUUID as randomUUID8 } from "crypto";
|
|
27199
|
+
function assertRegularBackupTree(path2) {
|
|
27200
|
+
const stat2 = lstatSync(path2);
|
|
27201
|
+
if (stat2.isDirectory()) {
|
|
27202
|
+
for (const entry of readdirSync3(path2)) assertRegularBackupTree(`${path2}/${entry}`);
|
|
27203
|
+
return;
|
|
27204
|
+
}
|
|
27205
|
+
if (!stat2.isFile() || stat2.nlink !== 1) {
|
|
27206
|
+
throw new Error(`Backup archive refused unsafe entry: ${path2}`);
|
|
27207
|
+
}
|
|
27208
|
+
}
|
|
27209
|
+
function publishServerBackupArchive(sourceDir, archivePath, options = {}) {
|
|
27210
|
+
assertRegularBackupTree(sourceDir);
|
|
27211
|
+
const temporaryArchivePath = `${archivePath}.tmp-${randomUUID8()}`;
|
|
27212
|
+
const previousUmask = process.umask(63);
|
|
27213
|
+
try {
|
|
27214
|
+
execFileSync3(options.tarCommand ?? "tar", ["-czf", temporaryArchivePath, "-C", sourceDir, "."], { stdio: "pipe" });
|
|
27215
|
+
chmodSync3(temporaryArchivePath, 384);
|
|
27216
|
+
renameSync(temporaryArchivePath, archivePath);
|
|
27217
|
+
chmodSync3(archivePath, 384);
|
|
27218
|
+
} finally {
|
|
27219
|
+
process.umask(previousUmask);
|
|
27220
|
+
rmSync4(temporaryArchivePath, { force: true });
|
|
27221
|
+
}
|
|
27222
|
+
}
|
|
27223
|
+
|
|
27196
27224
|
// src/serverHealth.ts
|
|
27197
27225
|
import dnsModule, { promises as dns } from "dns";
|
|
27198
|
-
import { createHmac as createHmac4, randomUUID as
|
|
27226
|
+
import { createHmac as createHmac4, randomUUID as randomUUID9 } from "crypto";
|
|
27199
27227
|
import { promises as fs } from "fs";
|
|
27200
27228
|
import { isIP } from "net";
|
|
27201
27229
|
import { request as httpsRequest } from "https";
|
|
@@ -27578,7 +27606,7 @@ async function resolveGenericWebhookTarget(rawUrl, allowLocalDevelopmentFixture
|
|
|
27578
27606
|
async function sendGenericWebhook(target, secret, payload, allowLocalDevelopmentFixture = false) {
|
|
27579
27607
|
const { url, addresses } = await resolveGenericWebhookTarget(target, allowLocalDevelopmentFixture);
|
|
27580
27608
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
27581
|
-
const eventId =
|
|
27609
|
+
const eventId = randomUUID9();
|
|
27582
27610
|
const signed = signRuntimeWebhookPayload(payload, secret, timestamp, eventId);
|
|
27583
27611
|
const selected = addresses[0];
|
|
27584
27612
|
await new Promise((resolve11, reject) => {
|
|
@@ -27787,7 +27815,7 @@ function signRuntimeWebhookPayload(payload, secret, timestamp, eventId) {
|
|
|
27787
27815
|
|
|
27788
27816
|
// src/serverUpdateState.ts
|
|
27789
27817
|
import { randomBytes as randomBytes7 } from "crypto";
|
|
27790
|
-
import { chmodSync as
|
|
27818
|
+
import { chmodSync as chmodSync4, closeSync, existsSync as existsSync8, mkdirSync as mkdirSync5, openSync, readFileSync as readFileSync6, renameSync as renameSync2, rmSync as rmSync5, writeFileSync as writeFileSync4 } from "fs";
|
|
27791
27819
|
import { dirname as dirname5, join as join6 } from "path";
|
|
27792
27820
|
function serverUpdateStatusFile(installPath, role) {
|
|
27793
27821
|
return join6(installPath, ".openmates", `${role}-update-status.json`);
|
|
@@ -27811,8 +27839,8 @@ function writeServerUpdateStatus(installPath, role, status) {
|
|
|
27811
27839
|
const temporaryPath = `${filePath}.${process.pid}.${randomBytes7(4).toString("hex")}.tmp`;
|
|
27812
27840
|
writeFileSync4(temporaryPath, `${JSON.stringify({ role, updated_at: (/* @__PURE__ */ new Date()).toISOString(), ...status }, null, 2)}
|
|
27813
27841
|
`, { mode: 384 });
|
|
27814
|
-
|
|
27815
|
-
|
|
27842
|
+
renameSync2(temporaryPath, filePath);
|
|
27843
|
+
chmodSync4(filePath, 384);
|
|
27816
27844
|
}
|
|
27817
27845
|
function acquireServerUpdateLock(installPath) {
|
|
27818
27846
|
const stateDir2 = join6(installPath, ".openmates");
|
|
@@ -27839,13 +27867,13 @@ function acquireServerUpdateLock(installPath) {
|
|
|
27839
27867
|
return () => {
|
|
27840
27868
|
closeSync(descriptor);
|
|
27841
27869
|
if (existsSync8(lockPath) && readFileSync6(lockPath, "utf8").trim() === ownershipToken) {
|
|
27842
|
-
|
|
27870
|
+
rmSync5(lockPath);
|
|
27843
27871
|
}
|
|
27844
27872
|
};
|
|
27845
27873
|
}
|
|
27846
27874
|
|
|
27847
27875
|
// src/serverQuickTest.ts
|
|
27848
|
-
import { randomUUID as
|
|
27876
|
+
import { randomUUID as randomUUID10 } from "crypto";
|
|
27849
27877
|
var QUICK_TEST_RESPONSE_TIMEOUT_MS = 12e4;
|
|
27850
27878
|
var QUICK_TEST_WEB_QUERY = "site:openmates.org OpenMates";
|
|
27851
27879
|
var QUICK_TEST_EXPECTED_RESPONSE = "server quick test passed";
|
|
@@ -27911,7 +27939,7 @@ function decideQuickServerTestAction(input) {
|
|
|
27911
27939
|
async function runQuickServerTest(client, options = {}) {
|
|
27912
27940
|
const now = options.now ?? Date.now;
|
|
27913
27941
|
const checks = [];
|
|
27914
|
-
const chatId =
|
|
27942
|
+
const chatId = randomUUID10();
|
|
27915
27943
|
let chatMayExist = false;
|
|
27916
27944
|
checks.push({ id: "account.session", status: "passed", duration_ms: 0 });
|
|
27917
27945
|
const createStarted = now();
|
|
@@ -28042,6 +28070,7 @@ var HEALTH_REQUEST_TIMEOUT_MS = 5e3;
|
|
|
28042
28070
|
var CHECKSUM_BUFFER_BYTES = 1024 * 1024;
|
|
28043
28071
|
var ENV_BACKUP_PREFIX = ".env.openmates-backup-";
|
|
28044
28072
|
var ENV_BACKUP_RETENTION_COUNT = 5;
|
|
28073
|
+
var BACKUP_FORMAT_VERSION = 2;
|
|
28045
28074
|
var IMAGE_CHANNEL_TAGS = {
|
|
28046
28075
|
stable: MAIN_BRANCH,
|
|
28047
28076
|
main: MAIN_BRANCH,
|
|
@@ -28268,7 +28297,7 @@ function beginEngineeringRuntimeOperation(installPath, operationType, services)
|
|
|
28268
28297
|
"dev-stack"
|
|
28269
28298
|
];
|
|
28270
28299
|
for (const service of services) args.push("--service", service);
|
|
28271
|
-
const output =
|
|
28300
|
+
const output = execFileSync4("python3", args, {
|
|
28272
28301
|
cwd: installPath,
|
|
28273
28302
|
encoding: "utf-8",
|
|
28274
28303
|
stdio: ["ignore", "pipe", "pipe"]
|
|
@@ -28279,7 +28308,7 @@ function beginEngineeringRuntimeOperation(installPath, operationType, services)
|
|
|
28279
28308
|
}
|
|
28280
28309
|
function finishEngineeringRuntimeOperation(installPath, operationKey, status) {
|
|
28281
28310
|
const manager = join7(installPath, "scripts", "engineering_control_plane.py");
|
|
28282
|
-
|
|
28311
|
+
execFileSync4(
|
|
28283
28312
|
"python3",
|
|
28284
28313
|
[manager, "operation", "update", "--operation-key", operationKey, "--status", status],
|
|
28285
28314
|
{ cwd: installPath, stdio: ["ignore", "ignore", "pipe"] }
|
|
@@ -28939,13 +28968,13 @@ function targetSourceLinks(imageTag, templateRef) {
|
|
|
28939
28968
|
};
|
|
28940
28969
|
}
|
|
28941
28970
|
function installedImageMetadata(input) {
|
|
28942
|
-
const containerId =
|
|
28971
|
+
const containerId = execFileSync4(
|
|
28943
28972
|
"docker",
|
|
28944
28973
|
[...composeArgs(input.installPath, input.withOverrides, "image", input.role), "ps", "-q", ROLE_PROVENANCE_SERVICE[input.role]],
|
|
28945
28974
|
{ cwd: input.installPath, encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] }
|
|
28946
28975
|
).trim();
|
|
28947
28976
|
if (!containerId) throw new Error("updated_container_unavailable");
|
|
28948
|
-
const labels = JSON.parse(
|
|
28977
|
+
const labels = JSON.parse(execFileSync4(
|
|
28949
28978
|
"docker",
|
|
28950
28979
|
["inspect", "--format", "{{json .Config.Labels}}", containerId],
|
|
28951
28980
|
{ cwd: input.installPath, encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] }
|
|
@@ -29012,9 +29041,9 @@ function readEnvContent(installPath) {
|
|
|
29012
29041
|
return existsSync9(envPath) ? readFileSync7(envPath, "utf-8") : "";
|
|
29013
29042
|
}
|
|
29014
29043
|
function pruneEnvBackups(installPath) {
|
|
29015
|
-
const backups =
|
|
29044
|
+
const backups = readdirSync4(installPath, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.startsWith(ENV_BACKUP_PREFIX)).map((entry) => entry.name).sort();
|
|
29016
29045
|
for (const backup of backups.slice(0, Math.max(0, backups.length - ENV_BACKUP_RETENTION_COUNT))) {
|
|
29017
|
-
|
|
29046
|
+
rmSync6(join7(installPath, backup), { force: true });
|
|
29018
29047
|
}
|
|
29019
29048
|
}
|
|
29020
29049
|
function backupEnvFile(installPath) {
|
|
@@ -29022,7 +29051,7 @@ function backupEnvFile(installPath) {
|
|
|
29022
29051
|
if (!existsSync9(envPath)) return null;
|
|
29023
29052
|
const backupPath = join7(installPath, `${ENV_BACKUP_PREFIX}${nowStamp()}`);
|
|
29024
29053
|
copyFileSync2(envPath, backupPath);
|
|
29025
|
-
|
|
29054
|
+
chmodSync5(backupPath, 384);
|
|
29026
29055
|
pruneEnvBackups(installPath);
|
|
29027
29056
|
return backupPath;
|
|
29028
29057
|
}
|
|
@@ -29030,7 +29059,7 @@ function writeEnvContent(installPath, content) {
|
|
|
29030
29059
|
const envPath = envPathForInstall(installPath);
|
|
29031
29060
|
mkdirSync6(dirname6(envPath), { recursive: true });
|
|
29032
29061
|
writeFileSync5(envPath, content, { mode: 384 });
|
|
29033
|
-
|
|
29062
|
+
chmodSync5(envPath, 384);
|
|
29034
29063
|
}
|
|
29035
29064
|
function writeDeploymentModeEnv(installPath, deploymentMode, overlayPath) {
|
|
29036
29065
|
let content = readEnvContent(installPath);
|
|
@@ -29203,7 +29232,7 @@ for item in checks:
|
|
|
29203
29232
|
print(json.dumps({"ok": True, "presence": presence}))
|
|
29204
29233
|
`;
|
|
29205
29234
|
try {
|
|
29206
|
-
const output =
|
|
29235
|
+
const output = execFileSync4(
|
|
29207
29236
|
"docker",
|
|
29208
29237
|
["exec", "-e", `OPENMATES_SECRET_CHECKS=${JSON.stringify(checks)}`, container, "python", "-c", script],
|
|
29209
29238
|
{ encoding: "utf-8", timeout: 1e4, stdio: ["pipe", "pipe", "pipe"] }
|
|
@@ -29258,7 +29287,7 @@ function hashFile(path2) {
|
|
|
29258
29287
|
function writeChecksums(rootDir) {
|
|
29259
29288
|
const lines = [];
|
|
29260
29289
|
const walk = (dir) => {
|
|
29261
|
-
for (const entry of
|
|
29290
|
+
for (const entry of readdirSync4(dir, { withFileTypes: true })) {
|
|
29262
29291
|
const path2 = join7(dir, entry.name);
|
|
29263
29292
|
if (entry.isDirectory()) {
|
|
29264
29293
|
walk(path2);
|
|
@@ -29296,19 +29325,20 @@ function createServerBackup(installPath, role, options = {}) {
|
|
|
29296
29325
|
const backupDir = roleBackupDir(installPath, role);
|
|
29297
29326
|
mkdirSync6(backupDir, { recursive: true, mode: 448 });
|
|
29298
29327
|
const archivePath = options.output ? resolve6(options.output) : join7(backupDir, options.preUpdate ? `latest-pre-update-${role}.tar.gz` : `openmates-${role}-${nowStamp()}.tar.gz`);
|
|
29328
|
+
mkdirSync6(dirname6(archivePath), { recursive: true, mode: 448 });
|
|
29299
29329
|
const tempDir = mkdtempSync(join7(backupDir, ".tmp-"));
|
|
29300
29330
|
const env = readEnvMap(installPath);
|
|
29301
29331
|
const manifest = {
|
|
29302
29332
|
role,
|
|
29333
|
+
backup_format_version: BACKUP_FORMAT_VERSION,
|
|
29303
29334
|
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
29304
29335
|
cli_version: getPackageVersion(),
|
|
29305
29336
|
image_tag: getEnvVar(existsSync9(join7(installPath, ".env")) ? readFileSync7(join7(installPath, ".env"), "utf-8") : "", "OPENMATES_IMAGE_TAG"),
|
|
29306
|
-
|
|
29307
|
-
|
|
29337
|
+
recovery_scope: role === "core" ? "database-and-runtime-only" : "runtime-only",
|
|
29338
|
+
include_observability: false,
|
|
29339
|
+
contents: plan.contents.filter((content) => content !== "runtime-env" || existsSync9(join7(installPath, ".env"))).filter((content) => content !== "runtime-config" || existsSync9(join7(installPath, "config")))
|
|
29308
29340
|
};
|
|
29309
29341
|
try {
|
|
29310
|
-
writeFileSync5(join7(tempDir, "manifest.json"), `${JSON.stringify(manifest, null, 2)}
|
|
29311
|
-
`);
|
|
29312
29342
|
copyIfExists(join7(installPath, ".env"), join7(tempDir, "runtime", ".env"));
|
|
29313
29343
|
copyIfExists(join7(installPath, "config"), join7(tempDir, "runtime", "config"));
|
|
29314
29344
|
if (role === "core") {
|
|
@@ -29329,19 +29359,13 @@ function createServerBackup(installPath, role, options = {}) {
|
|
|
29329
29359
|
closeSync2(dumpFile);
|
|
29330
29360
|
}
|
|
29331
29361
|
}
|
|
29332
|
-
|
|
29333
|
-
|
|
29334
|
-
[join7(installPath, "backend", "core", "extensions"), join7(tempDir, "directus-extensions")],
|
|
29335
|
-
[join7(installPath, "backend", role, "vault"), join7(tempDir, `${role}-vault-config`)]
|
|
29336
|
-
]) {
|
|
29337
|
-
copyIfExists(item[0], item[1]);
|
|
29338
|
-
}
|
|
29362
|
+
writeFileSync5(join7(tempDir, "manifest.json"), `${JSON.stringify(manifest, null, 2)}
|
|
29363
|
+
`, { mode: 384 });
|
|
29339
29364
|
writeChecksums(tempDir);
|
|
29340
|
-
|
|
29341
|
-
chmodSync4(archivePath, plan.fileMode);
|
|
29365
|
+
publishServerBackupArchive(tempDir, archivePath);
|
|
29342
29366
|
return archivePath;
|
|
29343
29367
|
} finally {
|
|
29344
|
-
|
|
29368
|
+
rmSync6(tempDir, { recursive: true, force: true });
|
|
29345
29369
|
}
|
|
29346
29370
|
}
|
|
29347
29371
|
function restoreServerBackup(installPath, role, file) {
|
|
@@ -29357,19 +29381,30 @@ function restoreServerBackup(installPath, role, file) {
|
|
|
29357
29381
|
if (!existsSync9(manifestPath)) throw new Error("Backup archive is missing manifest.json.");
|
|
29358
29382
|
const manifest = JSON.parse(readFileSync7(manifestPath, "utf-8"));
|
|
29359
29383
|
if (manifest.role !== role) throw new Error(`Backup role '${manifest.role}' does not match requested role '${role}'.`);
|
|
29384
|
+
if (role === "core" && manifest.backup_format_version === BACKUP_FORMAT_VERSION && manifest.recovery_scope !== "full-core") {
|
|
29385
|
+
throw new Error("This backup records database and runtime state only; refusing unsafe full core restore.");
|
|
29386
|
+
}
|
|
29360
29387
|
copyIfExists(join7(tempDir, "runtime", ".env"), join7(installPath, ".env"));
|
|
29361
29388
|
copyIfExists(join7(tempDir, "runtime", "config"), join7(installPath, "config"));
|
|
29362
29389
|
const postgresDump = join7(tempDir, "postgres.sql");
|
|
29363
29390
|
if (role === "core" && existsSync9(postgresDump)) {
|
|
29364
29391
|
const databaseUser = env.DATABASE_USERNAME || "directus";
|
|
29365
29392
|
const databaseName = env.DATABASE_NAME || "directus";
|
|
29366
|
-
|
|
29367
|
-
|
|
29368
|
-
|
|
29369
|
-
|
|
29393
|
+
const dumpFile = openSync2(postgresDump, "r");
|
|
29394
|
+
try {
|
|
29395
|
+
const result = spawnSync(
|
|
29396
|
+
"docker",
|
|
29397
|
+
["exec", "-i", "cms-database", "psql", "-v", "ON_ERROR_STOP=1", "-U", databaseUser, databaseName],
|
|
29398
|
+
{ encoding: "utf-8", stdio: [dumpFile, "pipe", "pipe"] }
|
|
29399
|
+
);
|
|
29400
|
+
if (result.error) throw result.error;
|
|
29401
|
+
if (result.status !== 0) throw new Error(result.stderr || `psql exited with status ${result.status}`);
|
|
29402
|
+
} finally {
|
|
29403
|
+
closeSync2(dumpFile);
|
|
29404
|
+
}
|
|
29370
29405
|
}
|
|
29371
29406
|
} finally {
|
|
29372
|
-
|
|
29407
|
+
rmSync6(tempDir, { recursive: true, force: true });
|
|
29373
29408
|
}
|
|
29374
29409
|
}
|
|
29375
29410
|
function restoreStopServices(installPath, withOverrides, installMode, role) {
|
|
@@ -29992,7 +30027,7 @@ async function runUpdateCompletionEmailGate(input) {
|
|
|
29992
30027
|
deliveryId: deliveryPlan.deliveryId
|
|
29993
30028
|
};
|
|
29994
30029
|
}
|
|
29995
|
-
const deliveryId = deliveryPlan.deliveryId ??
|
|
30030
|
+
const deliveryId = deliveryPlan.deliveryId ?? randomUUID11();
|
|
29996
30031
|
const deliveryPendingAt = deliveryPlan.pendingAt ?? completedAt;
|
|
29997
30032
|
const previousAttempts = deliveryPlan.previousAttempts ?? 0;
|
|
29998
30033
|
const { role: _role, updated_at: _updatedAt, ...currentStatus } = readServerUpdateStatus(input.installPath, input.role);
|
|
@@ -30131,18 +30166,18 @@ async function installRuntimeMonitoringServices(installPath, role) {
|
|
|
30131
30166
|
const installedOperationalUnits = operationalUnitNames.filter((name) => existsSync9(join7("/etc", "systemd", "system", name)));
|
|
30132
30167
|
const installedOperationalTimers = installedOperationalUnits.filter((name) => name.endsWith(".timer"));
|
|
30133
30168
|
if (installedOperationalTimers.length) {
|
|
30134
|
-
|
|
30169
|
+
execFileSync4("systemctl", ["disable", "--now", ...installedOperationalTimers], { stdio: "pipe" });
|
|
30135
30170
|
}
|
|
30136
|
-
for (const name of installedOperationalUnits)
|
|
30171
|
+
for (const name of installedOperationalUnits) rmSync6(join7("/etc", "systemd", "system", name));
|
|
30137
30172
|
for (const path2 of [reportStatePath, startedMetricPath, successMetricPath]) {
|
|
30138
|
-
if (existsSync9(path2))
|
|
30173
|
+
if (existsSync9(path2)) rmSync6(path2);
|
|
30139
30174
|
}
|
|
30140
30175
|
}
|
|
30141
30176
|
for (const [name, content] of files) writeFileSync5(join7("/etc", "systemd", "system", name), content, { mode: 420 });
|
|
30142
30177
|
execSync("systemctl daemon-reload", { stdio: "pipe" });
|
|
30143
30178
|
const timers = files.filter(([name]) => name.endsWith(".timer")).map(([name]) => name);
|
|
30144
30179
|
execSync(`systemctl enable --now ${timers.map(shellQuote).join(" ")}`, { stdio: "pipe" });
|
|
30145
|
-
for (const timer of timers)
|
|
30180
|
+
for (const timer of timers) execFileSync4("systemctl", ["is-active", "--quiet", timer], { stdio: "pipe" });
|
|
30146
30181
|
}
|
|
30147
30182
|
async function autoInstallRuntimeMonitoringServices(installPath, role) {
|
|
30148
30183
|
if (!shouldAutoInstallRuntimeMonitoringServices(process.env)) {
|
|
@@ -31145,7 +31180,7 @@ async function serverBackup(rest, flags) {
|
|
|
31145
31180
|
const role = getServerRole(flags, config);
|
|
31146
31181
|
if (action === "list") {
|
|
31147
31182
|
const dir = roleBackupDir(installPath, role);
|
|
31148
|
-
const files = existsSync9(dir) ?
|
|
31183
|
+
const files = existsSync9(dir) ? readdirSync4(dir).filter((item) => item.endsWith(".tar.gz")).sort() : [];
|
|
31149
31184
|
if (flags.json === true) {
|
|
31150
31185
|
printJson({ role, backupDir: dir, files });
|
|
31151
31186
|
return;
|
|
@@ -31240,7 +31275,7 @@ async function serverUninstall(flags) {
|
|
|
31240
31275
|
} catch {
|
|
31241
31276
|
}
|
|
31242
31277
|
try {
|
|
31243
|
-
|
|
31278
|
+
rmSync6(installPath, { recursive: true, force: true });
|
|
31244
31279
|
console.error(` Removed installation directory: ${installPath}`);
|
|
31245
31280
|
} catch (e) {
|
|
31246
31281
|
console.error(` Could not remove ${installPath}: ${e instanceof Error ? e.message : e}`);
|
|
@@ -48913,9 +48948,9 @@ function basenameFromUrl(url) {
|
|
|
48913
48948
|
return withoutQuery.split("/").pop()?.replace(/[^a-zA-Z0-9._-]/g, "_") ?? "";
|
|
48914
48949
|
}
|
|
48915
48950
|
function extensionFromUrl(url) {
|
|
48916
|
-
const
|
|
48917
|
-
const dotIndex =
|
|
48918
|
-
return dotIndex > 0 ?
|
|
48951
|
+
const basename5 = basenameFromUrl(url);
|
|
48952
|
+
const dotIndex = basename5.lastIndexOf(".");
|
|
48953
|
+
return dotIndex > 0 ? basename5.slice(dotIndex + 1).toLowerCase() : "";
|
|
48919
48954
|
}
|
|
48920
48955
|
function extensionFromLanguage(language) {
|
|
48921
48956
|
const normalized = language.toLowerCase();
|
|
@@ -70488,8 +70523,8 @@ function buildAssistantFeedbackDecision(rating) {
|
|
|
70488
70523
|
}
|
|
70489
70524
|
|
|
70490
70525
|
// src/benchmark.ts
|
|
70491
|
-
import { createHash as createHash13, randomUUID as
|
|
70492
|
-
import { existsSync as existsSync10, mkdtempSync as mkdtempSync2, readFileSync as readFileSync8, readdirSync as
|
|
70526
|
+
import { createHash as createHash13, randomUUID as randomUUID12 } from "crypto";
|
|
70527
|
+
import { existsSync as existsSync10, mkdtempSync as mkdtempSync2, readFileSync as readFileSync8, readdirSync as readdirSync5, writeFileSync as writeFileSync6 } from "fs";
|
|
70493
70528
|
import { tmpdir } from "os";
|
|
70494
70529
|
import { dirname as dirname7, join as join8, resolve as resolve8 } from "path";
|
|
70495
70530
|
import { fileURLToPath } from "url";
|
|
@@ -70904,7 +70939,7 @@ async function handleBenchmark(client, subcommand, rest, flags) {
|
|
|
70904
70939
|
const caseIds = parseCaseIds(flags.case);
|
|
70905
70940
|
const dryRun = flags["dry-run"] === true;
|
|
70906
70941
|
const output = typeof flags.output === "string" ? flags.output : void 0;
|
|
70907
|
-
const runId = typeof flags["run-id"] === "string" ? flags["run-id"] :
|
|
70942
|
+
const runId = typeof flags["run-id"] === "string" ? flags["run-id"] : randomUUID12();
|
|
70908
70943
|
const imagePath = typeof flags.image === "string" ? resolve8(flags.image) : defaultImageFixturePath();
|
|
70909
70944
|
if (!dryRun && flags["confirm-spend-credits"] !== true) {
|
|
70910
70945
|
throw new Error(
|
|
@@ -71006,7 +71041,7 @@ async function handlePromptBudgetBenchmark(client, rest, flags) {
|
|
|
71006
71041
|
if (resumeArtifact) {
|
|
71007
71042
|
validatePromptBudgetResumeArtifact(resumeArtifact, { phase, targetModel, judgeModel });
|
|
71008
71043
|
}
|
|
71009
|
-
const runId = stringFlag(flags["run-id"]) ?? resumeArtifact?.runId ??
|
|
71044
|
+
const runId = stringFlag(flags["run-id"]) ?? resumeArtifact?.runId ?? randomUUID12();
|
|
71010
71045
|
const result = makePromptBudgetBaseResult({
|
|
71011
71046
|
phase,
|
|
71012
71047
|
runId,
|
|
@@ -71567,7 +71602,7 @@ function buildLongContextHistory() {
|
|
|
71567
71602
|
}
|
|
71568
71603
|
function appendHistory(history, role, content) {
|
|
71569
71604
|
history.push({
|
|
71570
|
-
message_id:
|
|
71605
|
+
message_id: randomUUID12(),
|
|
71571
71606
|
role,
|
|
71572
71607
|
sender_name: role === "user" ? "User" : "Assistant",
|
|
71573
71608
|
content,
|
|
@@ -71657,7 +71692,7 @@ function loadProviderPricing() {
|
|
|
71657
71692
|
const providersDir = findProvidersDir();
|
|
71658
71693
|
const pricing = /* @__PURE__ */ new Map();
|
|
71659
71694
|
if (!providersDir) return pricing;
|
|
71660
|
-
for (const fileName of
|
|
71695
|
+
for (const fileName of readdirSync5(providersDir)) {
|
|
71661
71696
|
if (!fileName.endsWith(".yml")) continue;
|
|
71662
71697
|
const filePath = join8(providersDir, fileName);
|
|
71663
71698
|
const text = readFileSync8(filePath, "utf-8");
|
|
@@ -73434,7 +73469,7 @@ function clamp(value, min, max) {
|
|
|
73434
73469
|
// src/remoteAccess.ts
|
|
73435
73470
|
import { homedir as homedir7 } from "os";
|
|
73436
73471
|
import {
|
|
73437
|
-
chmodSync as
|
|
73472
|
+
chmodSync as chmodSync6,
|
|
73438
73473
|
closeSync as closeSync3,
|
|
73439
73474
|
constants,
|
|
73440
73475
|
existsSync as existsSync11,
|
|
@@ -73442,7 +73477,7 @@ import {
|
|
|
73442
73477
|
mkdirSync as mkdirSync7,
|
|
73443
73478
|
openSync as openSync3,
|
|
73444
73479
|
readFileSync as readFileSync9,
|
|
73445
|
-
readdirSync as
|
|
73480
|
+
readdirSync as readdirSync6,
|
|
73446
73481
|
readSync as readSync2,
|
|
73447
73482
|
realpathSync,
|
|
73448
73483
|
statSync as statSync2,
|
|
@@ -73586,7 +73621,7 @@ function discoverRemoteAccessRepositories(roots) {
|
|
|
73586
73621
|
const visit = (directory, approvedRoot) => {
|
|
73587
73622
|
let entries;
|
|
73588
73623
|
try {
|
|
73589
|
-
entries =
|
|
73624
|
+
entries = readdirSync6(directory, { withFileTypes: true });
|
|
73590
73625
|
} catch (error) {
|
|
73591
73626
|
const code = error.code;
|
|
73592
73627
|
if (code === "EACCES" || code === "EPERM") {
|
|
@@ -73624,7 +73659,7 @@ function listRemoteAccessDirectory(options) {
|
|
|
73624
73659
|
const entries = [];
|
|
73625
73660
|
let omitted = 0;
|
|
73626
73661
|
let excluded = 0;
|
|
73627
|
-
for (const entry of
|
|
73662
|
+
for (const entry of readdirSync6(directory, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
|
|
73628
73663
|
const entryPath = relative2(root, join9(directory, entry.name)).replace(/\\/g, "/");
|
|
73629
73664
|
if (entry.name === ".git" || entry.isSymbolicLink() || isGitIgnoredPath(root, entryPath) || classifyProjectFileRisk(entryPath, options.userProtectedPatterns ?? []).isHighRisk || entry.isFile() && isBinaryFile(join9(directory, entry.name))) {
|
|
73630
73665
|
excluded += 1;
|
|
@@ -73972,7 +74007,7 @@ function searchRemoteSourceWithoutRg(query, sourceRoot, maxResults, userProtecte
|
|
|
73972
74007
|
const directory = directories.pop();
|
|
73973
74008
|
let entries;
|
|
73974
74009
|
try {
|
|
73975
|
-
entries =
|
|
74010
|
+
entries = readdirSync6(directory, { withFileTypes: true }).sort((left, right) => left.name.localeCompare(right.name));
|
|
73976
74011
|
} catch {
|
|
73977
74012
|
excluded += 1;
|
|
73978
74013
|
continue;
|
|
@@ -74185,10 +74220,10 @@ function saveRemoteAccessSources(sources, homeDirectory) {
|
|
|
74185
74220
|
const filePath = remoteAccessStorePath(homeDirectory);
|
|
74186
74221
|
const stateDir2 = join9(homeDirectory, ".openmates");
|
|
74187
74222
|
mkdirSync7(stateDir2, { recursive: true, mode: 448 });
|
|
74188
|
-
|
|
74223
|
+
chmodSync6(stateDir2, 448);
|
|
74189
74224
|
writeFileSync7(filePath, `${JSON.stringify({ sources }, null, 2)}
|
|
74190
74225
|
`, { mode: 384 });
|
|
74191
|
-
|
|
74226
|
+
chmodSync6(filePath, 384);
|
|
74192
74227
|
}
|
|
74193
74228
|
function assertRemoteAccessSourceRecord(value, index) {
|
|
74194
74229
|
if (typeof value !== "object" || value === null) {
|
|
@@ -74206,7 +74241,7 @@ function assertRemoteAccessSourceRecord(value, index) {
|
|
|
74206
74241
|
}
|
|
74207
74242
|
|
|
74208
74243
|
// src/projectRequester.ts
|
|
74209
|
-
import { randomUUID as
|
|
74244
|
+
import { randomUUID as randomUUID13 } from "crypto";
|
|
74210
74245
|
var REMOTE_PROTOCOL_TIMEOUT_MS = 45e3;
|
|
74211
74246
|
var REMOTE_POLL_INTERVAL_MS = 250;
|
|
74212
74247
|
var MAX_REMOTE_RESULT_BYTES = 200 * 1024;
|
|
@@ -74232,8 +74267,8 @@ async function requestProjectRemoteOperation(options) {
|
|
|
74232
74267
|
keyEpoch = discovery.keyEpoch;
|
|
74233
74268
|
routingIdentity = discovery.routingIdentity;
|
|
74234
74269
|
}
|
|
74235
|
-
const requestingClientId =
|
|
74236
|
-
const requestId =
|
|
74270
|
+
const requestingClientId = randomUUID13();
|
|
74271
|
+
const requestId = randomUUID13();
|
|
74237
74272
|
const identity = await buildIdentity(
|
|
74238
74273
|
options.client,
|
|
74239
74274
|
options.projectId,
|
|
@@ -74294,9 +74329,9 @@ async function requestProjectRemoteOperation(options) {
|
|
|
74294
74329
|
return response.result;
|
|
74295
74330
|
}
|
|
74296
74331
|
async function discoverRouting(options, timeoutMs) {
|
|
74297
|
-
const requestId =
|
|
74298
|
-
const requestingClientId =
|
|
74299
|
-
const nonce =
|
|
74332
|
+
const requestId = randomUUID13();
|
|
74333
|
+
const requestingClientId = randomUUID13();
|
|
74334
|
+
const nonce = randomUUID13();
|
|
74300
74335
|
const encryptedEnvelope = await encryptWithAesGcmCombined(JSON.stringify({
|
|
74301
74336
|
type: "routing_discovery",
|
|
74302
74337
|
requesting_client_id: requestingClientId,
|
|
@@ -74394,9 +74429,64 @@ function remoteErrorMessage(code) {
|
|
|
74394
74429
|
|
|
74395
74430
|
// src/selfUpdate.ts
|
|
74396
74431
|
import { spawnSync as spawnSync3 } from "child_process";
|
|
74397
|
-
import { readFileSync as readFileSync10 } from "fs";
|
|
74432
|
+
import { readFileSync as readFileSync10, mkdirSync as mkdirSync8, writeFileSync as writeFileSync8, renameSync as renameSync3 } from "fs";
|
|
74433
|
+
import { homedir as homedir8 } from "os";
|
|
74434
|
+
import { dirname as dirname8, basename as basename3, join as join10 } from "path";
|
|
74435
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
74398
74436
|
var PACKAGE_NAME = "openmates";
|
|
74399
|
-
|
|
74437
|
+
function channelFile() {
|
|
74438
|
+
return join10(homedir8(), ".openmates", "updates.json");
|
|
74439
|
+
}
|
|
74440
|
+
function parseChannel(value) {
|
|
74441
|
+
if (value === "dev") return "dev";
|
|
74442
|
+
if (value === "stable" || value === "main") return "stable";
|
|
74443
|
+
throw new Error("--channel must be dev, stable, or main (alias for stable)");
|
|
74444
|
+
}
|
|
74445
|
+
function savedChannel() {
|
|
74446
|
+
try {
|
|
74447
|
+
return parseChannel(JSON.parse(readFileSync10(channelFile(), "utf8")).channel);
|
|
74448
|
+
} catch (error) {
|
|
74449
|
+
if (error.code === "ENOENT") {
|
|
74450
|
+
return getCliPackageVersion().includes("-") ? "dev" : "stable";
|
|
74451
|
+
}
|
|
74452
|
+
throw error;
|
|
74453
|
+
}
|
|
74454
|
+
}
|
|
74455
|
+
function persistSelfUpdateChannel(plan) {
|
|
74456
|
+
if (plan.dryRun || !plan.persistChannel) return;
|
|
74457
|
+
const path2 = channelFile();
|
|
74458
|
+
mkdirSync8(dirname8(path2), { recursive: true, mode: 448 });
|
|
74459
|
+
const temporary = `${path2}.${process.pid}.tmp`;
|
|
74460
|
+
writeFileSync8(temporary, JSON.stringify({ channel: plan.channel }) + "\n", { mode: 384 });
|
|
74461
|
+
renameSync3(temporary, path2);
|
|
74462
|
+
}
|
|
74463
|
+
function installedNpmPrefix(moduleUrl = import.meta.url, platform4 = process.platform) {
|
|
74464
|
+
const packageRoot = dirname8(dirname8(fileURLToPath2(moduleUrl)));
|
|
74465
|
+
const modules = dirname8(packageRoot);
|
|
74466
|
+
if (basename3(packageRoot) !== PACKAGE_NAME || basename3(modules) !== "node_modules") return null;
|
|
74467
|
+
if (platform4 === "win32") return dirname8(modules);
|
|
74468
|
+
return basename3(dirname8(modules)) === "lib" ? dirname8(dirname8(modules)) : null;
|
|
74469
|
+
}
|
|
74470
|
+
function compareVersions(left, right) {
|
|
74471
|
+
const parse = (value) => {
|
|
74472
|
+
const match = /^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/.exec(value);
|
|
74473
|
+
if (!match) throw new Error(`Cannot compare CLI version '${value}'`);
|
|
74474
|
+
return { core: match.slice(1, 4).map(BigInt), pre: match[4]?.split(".") };
|
|
74475
|
+
};
|
|
74476
|
+
const a = parse(left), b = parse(right);
|
|
74477
|
+
for (let i = 0; i < 3; i++) if (a.core[i] !== b.core[i]) return a.core[i] > b.core[i] ? 1 : -1;
|
|
74478
|
+
if (!a.pre || !b.pre) return a.pre ? -1 : b.pre ? 1 : 0;
|
|
74479
|
+
for (let i = 0; i < Math.max(a.pre.length, b.pre.length); i++) {
|
|
74480
|
+
const x = a.pre[i], y = b.pre[i];
|
|
74481
|
+
if (x === y) continue;
|
|
74482
|
+
if (x === void 0 || y === void 0) return x === void 0 ? -1 : 1;
|
|
74483
|
+
const nx = /^\d+$/.test(x), ny = /^\d+$/.test(y);
|
|
74484
|
+
if (nx && ny) return BigInt(x) > BigInt(y) ? 1 : BigInt(x) < BigInt(y) ? -1 : 0;
|
|
74485
|
+
if (nx !== ny) return nx ? -1 : 1;
|
|
74486
|
+
return x > y ? 1 : -1;
|
|
74487
|
+
}
|
|
74488
|
+
return 0;
|
|
74489
|
+
}
|
|
74400
74490
|
var SAFE_TARGET_RE = /^[a-zA-Z0-9._@+~:-]+$/;
|
|
74401
74491
|
function getCliPackageVersion() {
|
|
74402
74492
|
try {
|
|
@@ -74408,10 +74498,14 @@ function getCliPackageVersion() {
|
|
|
74408
74498
|
}
|
|
74409
74499
|
function buildSelfUpdatePlan(flags) {
|
|
74410
74500
|
const packageManager = parsePackageManager(flags["package-manager"]);
|
|
74411
|
-
const
|
|
74501
|
+
const channel = flags.channel === void 0 ? savedChannel() : parseChannel(flags.channel);
|
|
74502
|
+
const target = parseTarget(flags.version ?? (channel === "dev" ? "alpha" : "latest"));
|
|
74412
74503
|
const packageSpec = `${PACKAGE_NAME}@${target}`;
|
|
74413
74504
|
const { command, args } = commandForPackageManager(packageManager, packageSpec);
|
|
74414
74505
|
return {
|
|
74506
|
+
channel,
|
|
74507
|
+
persistChannel: flags.channel !== void 0,
|
|
74508
|
+
allowDowngrade: flags["allow-downgrade"] === true,
|
|
74415
74509
|
packageManager,
|
|
74416
74510
|
command,
|
|
74417
74511
|
args,
|
|
@@ -74434,7 +74528,7 @@ function checkSelfUpdateStatus(plan) {
|
|
|
74434
74528
|
return {
|
|
74435
74529
|
currentVersion: plan.currentVersion,
|
|
74436
74530
|
latestVersion: latest.version,
|
|
74437
|
-
updateAvailable: plan.currentVersion
|
|
74531
|
+
updateAvailable: compareVersions(latest.version, plan.currentVersion) > 0 || plan.allowDowngrade && compareVersions(latest.version, plan.currentVersion) !== 0,
|
|
74438
74532
|
checkError: null
|
|
74439
74533
|
};
|
|
74440
74534
|
}
|
|
@@ -74464,7 +74558,8 @@ function resolveTargetVersion(target) {
|
|
|
74464
74558
|
}
|
|
74465
74559
|
const result = spawnSync3(commandName("npm"), ["view", `${PACKAGE_NAME}@${target}`, "version"], {
|
|
74466
74560
|
encoding: "utf-8",
|
|
74467
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
74561
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
74562
|
+
timeout: 3e4
|
|
74468
74563
|
});
|
|
74469
74564
|
if (result.error) return { version: null, error: result.error.message };
|
|
74470
74565
|
if (result.status !== 0) {
|
|
@@ -74480,7 +74575,7 @@ function parsePackageManager(value) {
|
|
|
74480
74575
|
throw new Error("--package-manager must be one of npm, pnpm, yarn, or bun");
|
|
74481
74576
|
}
|
|
74482
74577
|
function parseTarget(value) {
|
|
74483
|
-
if (value === void 0) return
|
|
74578
|
+
if (value === void 0) return "latest";
|
|
74484
74579
|
if (typeof value !== "string" || value.length === 0) {
|
|
74485
74580
|
throw new Error("--version requires a version or npm dist-tag");
|
|
74486
74581
|
}
|
|
@@ -74500,15 +74595,16 @@ function commandForPackageManager(packageManager, packageSpec) {
|
|
|
74500
74595
|
if (packageManager === "pnpm") return { command: commandName("pnpm"), args: ["add", "-g", packageSpec] };
|
|
74501
74596
|
if (packageManager === "yarn") return { command: commandName("yarn"), args: ["global", "add", packageSpec] };
|
|
74502
74597
|
if (packageManager === "bun") return { command: commandName("bun"), args: ["install", "-g", packageSpec] };
|
|
74503
|
-
|
|
74598
|
+
const prefix = installedNpmPrefix();
|
|
74599
|
+
return { command: commandName("npm"), args: ["install", "-g", packageSpec, ...prefix ? ["--prefix", prefix] : []] };
|
|
74504
74600
|
}
|
|
74505
74601
|
function commandName(name) {
|
|
74506
74602
|
return process.platform === "win32" ? `${name}.cmd` : name;
|
|
74507
74603
|
}
|
|
74508
74604
|
|
|
74509
74605
|
// src/workRecovery.ts
|
|
74510
|
-
import { mkdirSync as
|
|
74511
|
-
import { dirname as
|
|
74606
|
+
import { mkdirSync as mkdirSync9, renameSync as renameSync4, writeFileSync as writeFileSync9 } from "fs";
|
|
74607
|
+
import { dirname as dirname9 } from "path";
|
|
74512
74608
|
import { stringify } from "yaml";
|
|
74513
74609
|
async function projectPlanAssumption(plan, masterKey, assumption) {
|
|
74514
74610
|
const key = await planKeyFromRecord(plan.encrypted, masterKey);
|
|
@@ -74687,18 +74783,18 @@ function collectMismatchPaths(left, right, path2, mismatches) {
|
|
|
74687
74783
|
}
|
|
74688
74784
|
function writeWorkRecoveryAtomically(path2, document) {
|
|
74689
74785
|
validateWorkRecoveryDocument(document);
|
|
74690
|
-
|
|
74786
|
+
mkdirSync9(dirname9(path2), { recursive: true, mode: 448 });
|
|
74691
74787
|
const temporaryPath = `${path2}.tmp`;
|
|
74692
|
-
|
|
74693
|
-
|
|
74788
|
+
writeFileSync9(temporaryPath, stringify(document, { sortMapEntries: true, lineWidth: 0 }), { encoding: "utf8", mode: 384 });
|
|
74789
|
+
renameSync4(temporaryPath, path2);
|
|
74694
74790
|
}
|
|
74695
74791
|
|
|
74696
74792
|
// src/revolutBusinessCertificate.ts
|
|
74697
|
-
import { execFileSync as
|
|
74698
|
-
import { createSign, randomUUID as
|
|
74699
|
-
import { chmodSync as
|
|
74700
|
-
import { homedir as
|
|
74701
|
-
import { join as
|
|
74793
|
+
import { execFileSync as execFileSync5 } from "child_process";
|
|
74794
|
+
import { createSign, randomUUID as randomUUID14 } from "crypto";
|
|
74795
|
+
import { chmodSync as chmodSync7, existsSync as existsSync12, mkdirSync as mkdirSync10, readFileSync as readFileSync11 } from "fs";
|
|
74796
|
+
import { homedir as homedir9 } from "os";
|
|
74797
|
+
import { join as join11, resolve as resolve10 } from "path";
|
|
74702
74798
|
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";
|
|
74703
74799
|
var REVOLUT_BUSINESS_DEFAULT_SANDBOX_REDIRECT_URI = "https://app.dev.openmates.org/oauth/revolut-business/callback";
|
|
74704
74800
|
var REVOLUT_BUSINESS_DEFAULT_PRODUCTION_REDIRECT_URI = "https://openmates.org/oauth/revolut-business/callback";
|
|
@@ -74708,7 +74804,7 @@ var REVOLUT_BUSINESS_AUDIENCE = "https://revolut.com";
|
|
|
74708
74804
|
var CERTIFICATE_DAYS = "1825";
|
|
74709
74805
|
var RSA_BITS = "2048";
|
|
74710
74806
|
function defaultRevolutBusinessCertificateDir(environment) {
|
|
74711
|
-
return
|
|
74807
|
+
return join11(homedir9(), ".openmates", "revolut-business", environment);
|
|
74712
74808
|
}
|
|
74713
74809
|
function defaultRevolutBusinessRedirectUri(environment) {
|
|
74714
74810
|
return environment === "sandbox" ? REVOLUT_BUSINESS_DEFAULT_SANDBOX_REDIRECT_URI : REVOLUT_BUSINESS_DEFAULT_PRODUCTION_REDIRECT_URI;
|
|
@@ -74731,7 +74827,7 @@ async function exchangeRevolutBusinessAuthorizationCode(options) {
|
|
|
74731
74827
|
if (!clientId) throw new Error("Missing Revolut Business client ID.");
|
|
74732
74828
|
const code = extractRevolutBusinessAuthorizationCode(options.codeOrRedirectUrl);
|
|
74733
74829
|
if (!code) throw new Error("Missing Revolut Business authorization code.");
|
|
74734
|
-
const privateKeyPem = options.privateKeyPem ?? readFileSync11(options.privateKeyPath ??
|
|
74830
|
+
const privateKeyPem = options.privateKeyPem ?? readFileSync11(options.privateKeyPath ?? join11(defaultRevolutBusinessCertificateDir(environment), "privatecert.pem"), "utf8");
|
|
74735
74831
|
const redirectUri = (options.redirectUri ?? defaultRevolutBusinessRedirectUri(environment)).trim();
|
|
74736
74832
|
const clientAssertion = generateRevolutBusinessClientAssertion({ clientId, privateKeyPem, redirectUri });
|
|
74737
74833
|
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", {
|
|
@@ -74769,7 +74865,7 @@ function generateRevolutBusinessClientAssertion(options) {
|
|
|
74769
74865
|
aud: REVOLUT_BUSINESS_AUDIENCE,
|
|
74770
74866
|
exp: now + 3600,
|
|
74771
74867
|
iat: now,
|
|
74772
|
-
jti:
|
|
74868
|
+
jti: randomUUID14()
|
|
74773
74869
|
});
|
|
74774
74870
|
const unsigned = `${header2}.${payload}`;
|
|
74775
74871
|
const signer = createSign("RSA-SHA256");
|
|
@@ -74784,17 +74880,17 @@ function generateRevolutBusinessCertificate(options = {}) {
|
|
|
74784
74880
|
const redirectUri = (options.redirectUri ?? defaultRevolutBusinessRedirectUri(environment)).trim();
|
|
74785
74881
|
if (!title) throw new Error("Revolut certificate title must not be empty.");
|
|
74786
74882
|
if (!redirectUri.startsWith("https://")) throw new Error("Revolut OAuth redirect URI must start with https://.");
|
|
74787
|
-
|
|
74788
|
-
|
|
74789
|
-
const privateKeyPath =
|
|
74790
|
-
const publicCertificatePath =
|
|
74883
|
+
mkdirSync10(outputDir, { recursive: true, mode: 448 });
|
|
74884
|
+
chmodSync7(outputDir, 448);
|
|
74885
|
+
const privateKeyPath = join11(outputDir, "privatecert.pem");
|
|
74886
|
+
const publicCertificatePath = join11(outputDir, "publiccert.cer");
|
|
74791
74887
|
if (!options.overwrite && (existsSync12(privateKeyPath) || existsSync12(publicCertificatePath))) {
|
|
74792
74888
|
throw new Error(`Revolut certificate files already exist in ${outputDir}. Re-run with --overwrite to replace them.`);
|
|
74793
74889
|
}
|
|
74794
74890
|
try {
|
|
74795
|
-
|
|
74796
|
-
|
|
74797
|
-
|
|
74891
|
+
execFileSync5("openssl", ["genrsa", "-out", privateKeyPath, RSA_BITS], { stdio: "ignore" });
|
|
74892
|
+
chmodSync7(privateKeyPath, 384);
|
|
74893
|
+
execFileSync5(
|
|
74798
74894
|
"openssl",
|
|
74799
74895
|
[
|
|
74800
74896
|
"req",
|
|
@@ -75252,11 +75348,14 @@ function handleSupport(flags) {
|
|
|
75252
75348
|
function handleSelfUpdate(command, flags) {
|
|
75253
75349
|
const plan = buildSelfUpdatePlan(flags);
|
|
75254
75350
|
const status = checkSelfUpdateStatus(plan);
|
|
75255
|
-
|
|
75351
|
+
if (status.checkError) throw new Error(`Update check failed: ${status.checkError}`);
|
|
75352
|
+
const shouldInstall = status.updateAvailable === true;
|
|
75256
75353
|
if (flags.json === true) {
|
|
75257
75354
|
if (!plan.dryRun && shouldInstall) runSelfUpdate(plan, { verbose: flags.verbose === true });
|
|
75355
|
+
persistSelfUpdateChannel(plan);
|
|
75258
75356
|
printJson2({
|
|
75259
75357
|
command,
|
|
75358
|
+
channel: plan.channel,
|
|
75260
75359
|
status: status.updateAvailable === false ? "up_to_date" : plan.dryRun ? "planned" : "success",
|
|
75261
75360
|
current_version: plan.currentVersion,
|
|
75262
75361
|
latest_version: status.latestVersion,
|
|
@@ -75273,6 +75372,7 @@ function handleSelfUpdate(command, flags) {
|
|
|
75273
75372
|
console.log("");
|
|
75274
75373
|
console.log("Checking for updates...");
|
|
75275
75374
|
console.log("");
|
|
75375
|
+
console.log(`Release channel: ${plan.channel}`);
|
|
75276
75376
|
console.log(`Current version: ${plan.currentVersion}`);
|
|
75277
75377
|
console.log(`Latest version: ${status.latestVersion ?? "unknown"}`);
|
|
75278
75378
|
if (status.checkError) {
|
|
@@ -75288,11 +75388,13 @@ function handleSelfUpdate(command, flags) {
|
|
|
75288
75388
|
return;
|
|
75289
75389
|
}
|
|
75290
75390
|
if (status.updateAvailable === false) {
|
|
75391
|
+
persistSelfUpdateChannel(plan);
|
|
75291
75392
|
console.log("OpenMates CLI is already up to date.");
|
|
75292
75393
|
return;
|
|
75293
75394
|
}
|
|
75294
75395
|
console.log(`Updating OpenMates CLI with ${plan.packageManager}...`);
|
|
75295
75396
|
runSelfUpdate(plan, { verbose: flags.verbose === true });
|
|
75397
|
+
persistSelfUpdateChannel(plan);
|
|
75296
75398
|
console.log(`Installed OpenMates CLI ${status.latestVersion ?? plan.target}.`);
|
|
75297
75399
|
console.log("");
|
|
75298
75400
|
console.log("OpenMates is up to date.");
|
|
@@ -75305,6 +75407,7 @@ function handleCliVersion(flags) {
|
|
|
75305
75407
|
if (flags.json === true) {
|
|
75306
75408
|
printJson2({
|
|
75307
75409
|
command: "version",
|
|
75410
|
+
channel: plan.channel,
|
|
75308
75411
|
current_version: status.currentVersion,
|
|
75309
75412
|
latest_version: status.latestVersion,
|
|
75310
75413
|
update_available: status.updateAvailable,
|
|
@@ -75314,6 +75417,7 @@ function handleCliVersion(flags) {
|
|
|
75314
75417
|
return;
|
|
75315
75418
|
}
|
|
75316
75419
|
console.log(`OpenMates CLI ${status.currentVersion}`);
|
|
75420
|
+
console.log(`Release channel: ${plan.channel}`);
|
|
75317
75421
|
if (status.checkError) {
|
|
75318
75422
|
console.log(`Update check failed: ${status.checkError}`);
|
|
75319
75423
|
return;
|
|
@@ -76081,7 +76185,7 @@ async function resolveAddToProjectStorageChoice(client, project, flags, objectTy
|
|
|
76081
76185
|
async function createEncryptedProjectItem(client, project, input) {
|
|
76082
76186
|
const timestamp = nowSeconds3();
|
|
76083
76187
|
return client.createProjectItem(project.projectId, {
|
|
76084
|
-
project_item_id:
|
|
76188
|
+
project_item_id: randomUUID15(),
|
|
76085
76189
|
folder_id: input.folderId ?? null,
|
|
76086
76190
|
item_type: input.itemType,
|
|
76087
76191
|
target_id: input.targetId,
|
|
@@ -76275,7 +76379,7 @@ async function handlePlans(client, subcommand, rest, flags, redactor) {
|
|
|
76275
76379
|
const encryptedSources = proof.length ? await encryptPlanAssumptionSources(plan, masterKey, proof) : void 0;
|
|
76276
76380
|
if (action === "create" || action === "add") {
|
|
76277
76381
|
const assumption = await client.createPlanAssumption(plan.planId, {
|
|
76278
|
-
assumption_id: typeof flags.id === "string" ? flags.id :
|
|
76382
|
+
assumption_id: typeof flags.id === "string" ? flags.id : randomUUID15(),
|
|
76279
76383
|
encrypted_text: await encryptPlanAssumptionSources(plan, masterKey, requiredStringFlag(flags.text ?? rest.slice(2).join(" "), "--text <assumption>")),
|
|
76280
76384
|
status: typeof flags.status === "string" ? flags.status : void 0,
|
|
76281
76385
|
linked_sub_chat_id: typeof flags["sub-chat"] === "string" ? flags["sub-chat"] : void 0,
|
|
@@ -77200,7 +77304,7 @@ async function handleProjects(client, subcommand, rest, flags, redactor) {
|
|
|
77200
77304
|
const name = requiredStringFlag(rest[0] ?? flags.name, "project name");
|
|
77201
77305
|
const projectKey = randomBytes9(32);
|
|
77202
77306
|
const wrapping = await client.projectWrappingKey(context);
|
|
77203
|
-
const projectId =
|
|
77307
|
+
const projectId = randomUUID15();
|
|
77204
77308
|
const timestamp = nowSeconds3();
|
|
77205
77309
|
const slugMetadata = await buildEncryptedObjectSlugMetadata({
|
|
77206
77310
|
value: typeof flags.slug === "string" ? flags.slug : name,
|
|
@@ -77308,7 +77412,7 @@ async function handleProjects(client, subcommand, rest, flags, redactor) {
|
|
|
77308
77412
|
const proposal = isShortWorkspaceAsk(instruction) ? { name: instruction, description: "", icon: "folder", color: "default" } : extractRecord(await client.planProjectAsk({ instruction }), "proposed_project");
|
|
77309
77413
|
const projectKey = randomBytes9(32);
|
|
77310
77414
|
const timestamp = Math.floor(Date.now() / 1e3);
|
|
77311
|
-
const projectId =
|
|
77415
|
+
const projectId = randomUUID15();
|
|
77312
77416
|
const name = requiredString(proposal, "name", instruction);
|
|
77313
77417
|
const slugMetadata = await buildEncryptedObjectSlugMetadata({
|
|
77314
77418
|
value: typeof flags.slug === "string" ? flags.slug : name,
|
|
@@ -77705,7 +77809,7 @@ async function handleTeams(client, subcommand, rest, flags) {
|
|
|
77705
77809
|
if (action === "get") {
|
|
77706
77810
|
const output = requiredStringFlag(flags.output ?? flags.file ?? rest[2], "--output <path>");
|
|
77707
77811
|
const image = await client.getTeamProfileImage(teamId);
|
|
77708
|
-
|
|
77812
|
+
writeFileSync10(output, image.data, { mode: 384 });
|
|
77709
77813
|
if (flags.json === true) printJson2({ output, content_type: image.contentType, size_bytes: image.data.byteLength });
|
|
77710
77814
|
else console.log(`Team profile image written: ${output}`);
|
|
77711
77815
|
return;
|
|
@@ -77864,7 +77968,7 @@ async function handleTeams(client, subcommand, rest, flags) {
|
|
|
77864
77968
|
const output = requiredStringFlag(flags.output, "--output <path>");
|
|
77865
77969
|
const result = await client.exportTeamData(teamId);
|
|
77866
77970
|
const artifact = result.artifact && typeof result.artifact === "object" ? result.artifact : result;
|
|
77867
|
-
|
|
77971
|
+
writeFileSync10(output, `${JSON.stringify(artifact, null, 2)}
|
|
77868
77972
|
`, { encoding: "utf-8", mode: 384 });
|
|
77869
77973
|
if (flags.json === true) printJson2({ ...result, output });
|
|
77870
77974
|
else console.log(`Team export written: ${output}`);
|
|
@@ -78207,7 +78311,7 @@ async function handleRemoteAccess(client, subcommand, rest, flags) {
|
|
|
78207
78311
|
const projects = await loadProjects(client, masterKey, hostingFlags, hostingContext);
|
|
78208
78312
|
const bindings = await resolveRemoteAccessBindings(client, masterKey, projects, candidateRoots, hostingFlags, hostingContext);
|
|
78209
78313
|
if (bindings.length === 0) throw new Error("No Project folders were approved for remote access.");
|
|
78210
|
-
const sourceSessionId =
|
|
78314
|
+
const sourceSessionId = randomUUID15();
|
|
78211
78315
|
const controller = new AbortController();
|
|
78212
78316
|
const stop = () => controller.abort();
|
|
78213
78317
|
process.once("SIGINT", stop);
|
|
@@ -78314,8 +78418,8 @@ async function resolveRemoteAccessBindings(client, masterKey, projects, candidat
|
|
|
78314
78418
|
const answer = (await promptLine2(`Create ${unresolved.length} missing Project${unresolved.length === 1 ? "" : "s"}? [y/N] `)).trim().toLowerCase();
|
|
78315
78419
|
if (answer !== "y" && answer !== "yes") throw new Error("Remote access Project creation cancelled.");
|
|
78316
78420
|
for (const rootPath of unresolved) {
|
|
78317
|
-
const project = await createEncryptedRemoteAccessProject(client, masterKey,
|
|
78318
|
-
resolved.push({ rootPath, project, sourceId:
|
|
78421
|
+
const project = await createEncryptedRemoteAccessProject(client, masterKey, basename4(rootPath), context);
|
|
78422
|
+
resolved.push({ rootPath, project, sourceId: randomUUID15() });
|
|
78319
78423
|
}
|
|
78320
78424
|
}
|
|
78321
78425
|
const bindings = [];
|
|
@@ -78326,7 +78430,7 @@ async function resolveRemoteAccessBindings(client, masterKey, projects, candidat
|
|
|
78326
78430
|
projectId: item.project.projectId,
|
|
78327
78431
|
rootPath: item.rootPath,
|
|
78328
78432
|
sourceType,
|
|
78329
|
-
displayName:
|
|
78433
|
+
displayName: basename4(item.rootPath)
|
|
78330
78434
|
});
|
|
78331
78435
|
const remoteSources = await client.listProjectSources(item.project.projectId, context);
|
|
78332
78436
|
const remoteSource = remoteSources.find((entry) => entry.source_id === source.sourceId);
|
|
@@ -78352,7 +78456,7 @@ async function resolveRemoteAccessBindings(client, masterKey, projects, candidat
|
|
|
78352
78456
|
}
|
|
78353
78457
|
async function createEncryptedRemoteAccessProject(client, masterKey, name, context) {
|
|
78354
78458
|
const projectKey = randomBytes9(32);
|
|
78355
|
-
const projectId =
|
|
78459
|
+
const projectId = randomUUID15();
|
|
78356
78460
|
const timestamp = Math.floor(Date.now() / 1e3);
|
|
78357
78461
|
const wrapping = await client.projectWrappingKey(context);
|
|
78358
78462
|
const payload = {
|
|
@@ -79169,16 +79273,16 @@ ${deleted}/${resolved.length} chat(s) deleted.`);
|
|
|
79169
79273
|
}
|
|
79170
79274
|
}
|
|
79171
79275
|
const { mkdir: mkdir2, writeFile: writeFile2 } = await import("fs/promises");
|
|
79172
|
-
const { join:
|
|
79276
|
+
const { join: join12 } = await import("path");
|
|
79173
79277
|
if (useZip) {
|
|
79174
|
-
const tmpDir =
|
|
79278
|
+
const tmpDir = join12(outputDir, `.${filenameBase}_tmp`);
|
|
79175
79279
|
await mkdir2(tmpDir, { recursive: true });
|
|
79176
|
-
await writeFile2(
|
|
79177
|
-
await writeFile2(
|
|
79280
|
+
await writeFile2(join12(tmpDir, `${filenameBase}.yml`), yamlContent);
|
|
79281
|
+
await writeFile2(join12(tmpDir, `${filenameBase}.md`), mdContent);
|
|
79178
79282
|
if (codeEmbeds.length > 0) {
|
|
79179
79283
|
for (const ce of codeEmbeds) {
|
|
79180
79284
|
const fpath = ce.filePath ?? ce.filename ?? `${ce.embedId.slice(0, 8)}.${getExtForLang(ce.language)}`;
|
|
79181
|
-
const fullPath =
|
|
79285
|
+
const fullPath = join12(tmpDir, "code", fpath);
|
|
79182
79286
|
await mkdir2(fullPath.substring(0, fullPath.lastIndexOf("/")), {
|
|
79183
79287
|
recursive: true
|
|
79184
79288
|
});
|
|
@@ -79186,13 +79290,13 @@ ${deleted}/${resolved.length} chat(s) deleted.`);
|
|
|
79186
79290
|
}
|
|
79187
79291
|
}
|
|
79188
79292
|
if (transcriptEmbeds.length > 0) {
|
|
79189
|
-
const tDir =
|
|
79293
|
+
const tDir = join12(tmpDir, "transcripts");
|
|
79190
79294
|
await mkdir2(tDir, { recursive: true });
|
|
79191
79295
|
for (const te of transcriptEmbeds) {
|
|
79192
|
-
await writeFile2(
|
|
79296
|
+
await writeFile2(join12(tDir, te.filename), te.content);
|
|
79193
79297
|
}
|
|
79194
79298
|
}
|
|
79195
|
-
const zipPath =
|
|
79299
|
+
const zipPath = join12(outputDir, `${filenameBase}.zip`);
|
|
79196
79300
|
const { execSync: execSync2 } = await import("child_process");
|
|
79197
79301
|
try {
|
|
79198
79302
|
execSync2(`cd "${tmpDir}" && zip -r "${zipPath}" .`, { stdio: "pipe" });
|
|
@@ -79207,17 +79311,17 @@ ${deleted}/${resolved.length} chat(s) deleted.`);
|
|
|
79207
79311
|
);
|
|
79208
79312
|
}
|
|
79209
79313
|
} else {
|
|
79210
|
-
const chatDir =
|
|
79314
|
+
const chatDir = join12(outputDir, filenameBase);
|
|
79211
79315
|
await mkdir2(chatDir, { recursive: true });
|
|
79212
79316
|
const written = [];
|
|
79213
|
-
await writeFile2(
|
|
79317
|
+
await writeFile2(join12(chatDir, `${filenameBase}.yml`), yamlContent);
|
|
79214
79318
|
written.push(`${filenameBase}.yml`);
|
|
79215
|
-
await writeFile2(
|
|
79319
|
+
await writeFile2(join12(chatDir, `${filenameBase}.md`), mdContent);
|
|
79216
79320
|
written.push(`${filenameBase}.md`);
|
|
79217
79321
|
if (codeEmbeds.length > 0) {
|
|
79218
79322
|
for (const ce of codeEmbeds) {
|
|
79219
79323
|
const fpath = ce.filePath ?? ce.filename ?? `${ce.embedId.slice(0, 8)}.${getExtForLang(ce.language)}`;
|
|
79220
|
-
const fullPath =
|
|
79324
|
+
const fullPath = join12(chatDir, "code", fpath);
|
|
79221
79325
|
await mkdir2(fullPath.substring(0, fullPath.lastIndexOf("/")), {
|
|
79222
79326
|
recursive: true
|
|
79223
79327
|
});
|
|
@@ -79226,10 +79330,10 @@ ${deleted}/${resolved.length} chat(s) deleted.`);
|
|
|
79226
79330
|
}
|
|
79227
79331
|
}
|
|
79228
79332
|
if (transcriptEmbeds.length > 0) {
|
|
79229
|
-
const tDir =
|
|
79333
|
+
const tDir = join12(chatDir, "transcripts");
|
|
79230
79334
|
await mkdir2(tDir, { recursive: true });
|
|
79231
79335
|
for (const te of transcriptEmbeds) {
|
|
79232
|
-
await writeFile2(
|
|
79336
|
+
await writeFile2(join12(tDir, te.filename), te.content);
|
|
79233
79337
|
written.push(`transcripts/${te.filename}`);
|
|
79234
79338
|
}
|
|
79235
79339
|
}
|
|
@@ -79265,7 +79369,7 @@ ${deleted}/${resolved.length} chat(s) deleted.`);
|
|
|
79265
79369
|
printJson2({
|
|
79266
79370
|
chat_id: chat.id,
|
|
79267
79371
|
title: chat.title,
|
|
79268
|
-
output_dir: useZip ?
|
|
79372
|
+
output_dir: useZip ? join12(outputDir, `${filenameBase}.zip`) : join12(outputDir, filenameBase),
|
|
79269
79373
|
files,
|
|
79270
79374
|
code_embeds: codeEmbeds.length,
|
|
79271
79375
|
transcript_embeds: transcriptEmbeds.length
|
|
@@ -80291,7 +80395,7 @@ function buildImagesAiDetectionSummary(uploadResult, filePath) {
|
|
|
80291
80395
|
const classification = classifyImagesAiDetection(score);
|
|
80292
80396
|
return {
|
|
80293
80397
|
file: filePath,
|
|
80294
|
-
filename: uploadResult.filename ||
|
|
80398
|
+
filename: uploadResult.filename || basename4(filePath),
|
|
80295
80399
|
content_type: uploadResult.content_type,
|
|
80296
80400
|
embed_id: uploadResult.embed_id,
|
|
80297
80401
|
deduplicated: uploadResult.deduplicated,
|
|
@@ -81322,7 +81426,7 @@ async function handleEmbeds(client, subcommand, rest, flags) {
|
|
|
81322
81426
|
throw new Error("Embed version content was not available after local reconstruction.");
|
|
81323
81427
|
}
|
|
81324
81428
|
if (typeof flags.output === "string") {
|
|
81325
|
-
|
|
81429
|
+
writeFileSync10(flags.output, result.content, "utf-8");
|
|
81326
81430
|
if (flags.json === true) {
|
|
81327
81431
|
printJson2({ ...result, output: flags.output });
|
|
81328
81432
|
} else {
|
|
@@ -81606,12 +81710,12 @@ async function parseAccountImportFile(parserFormat, file, flags = {}) {
|
|
|
81606
81710
|
const selectedSource = requestedSource;
|
|
81607
81711
|
if (parserFormat === "generic") {
|
|
81608
81712
|
if (selectedSource !== "gemini" && selectedSource !== "other") throw new Error("Generic account import requires --source gemini or --source other.");
|
|
81609
|
-
return parseGenericImportBuffer(payload,
|
|
81713
|
+
return parseGenericImportBuffer(payload, basename4(file), selectedSource);
|
|
81610
81714
|
}
|
|
81611
|
-
if (parserFormat === "claude") return parseClaudeImportBuffer(payload,
|
|
81612
|
-
if (parserFormat === "chatgpt") return parseChatGPTImportBuffer(payload,
|
|
81613
|
-
if (parserFormat === "opencode") return parseOpenCodeImportBuffer(payload,
|
|
81614
|
-
return parseOpenMatesImportBuffer(payload,
|
|
81715
|
+
if (parserFormat === "claude") return parseClaudeImportBuffer(payload, basename4(file), selectedSource);
|
|
81716
|
+
if (parserFormat === "chatgpt") return parseChatGPTImportBuffer(payload, basename4(file), selectedSource);
|
|
81717
|
+
if (parserFormat === "opencode") return parseOpenCodeImportBuffer(payload, basename4(file), selectedSource);
|
|
81718
|
+
return parseOpenMatesImportBuffer(payload, basename4(file), typeof flags.password === "string" ? flags.password : void 0, selectedSource);
|
|
81615
81719
|
}
|
|
81616
81720
|
async function runAccountImport(client, parserFormat, file, flags) {
|
|
81617
81721
|
if (parserFormat === "generic" && typeof flags.source !== "string") throw new Error("Generic account import requires --source gemini or --source other.");
|
|
@@ -81650,7 +81754,7 @@ async function runAccountImport(client, parserFormat, file, flags) {
|
|
|
81650
81754
|
if (flags.yes !== true) {
|
|
81651
81755
|
await confirmOrExit(`Import ${selectedCount} chat(s) into new encrypted OpenMates chats? [y/N] `);
|
|
81652
81756
|
}
|
|
81653
|
-
const importId = typeof preview.import_id === "string" ? preview.import_id :
|
|
81757
|
+
const importId = typeof preview.import_id === "string" ? preview.import_id : randomUUID15();
|
|
81654
81758
|
const selectedChats = parsed.chats.slice(0, selectedCount);
|
|
81655
81759
|
const selectedFingerprints = selectedChats.map((chat) => chat.source_fingerprint);
|
|
81656
81760
|
const confirmation = await client.confirmAccountImport(importId, selectedFingerprints);
|
|
@@ -81981,11 +82085,11 @@ function parseYamlScalar(value) {
|
|
|
81981
82085
|
}
|
|
81982
82086
|
async function saveDownloadedDocument(document, output) {
|
|
81983
82087
|
const { mkdir: mkdir2, writeFile: writeFile2 } = await import("fs/promises");
|
|
81984
|
-
const { join:
|
|
82088
|
+
const { join: join12, basename: basename5, dirname: dirname11 } = await import("path");
|
|
81985
82089
|
const target = typeof output === "string" ? output : ".";
|
|
81986
|
-
const filename =
|
|
81987
|
-
const filePath = target.endsWith(".pdf") ? target :
|
|
81988
|
-
await mkdir2(
|
|
82090
|
+
const filename = basename5(document.filename || "document.pdf");
|
|
82091
|
+
const filePath = target.endsWith(".pdf") ? target : join12(target, filename);
|
|
82092
|
+
await mkdir2(dirname11(filePath), { recursive: true });
|
|
81989
82093
|
await writeFile2(filePath, document.data);
|
|
81990
82094
|
return filePath;
|
|
81991
82095
|
}
|
|
@@ -82144,8 +82248,8 @@ async function handleFinance(client, subcommand, _rest, flags) {
|
|
|
82144
82248
|
refresh_token_envelope: connectedAccount.refreshTokenBundle
|
|
82145
82249
|
}
|
|
82146
82250
|
] : [],
|
|
82147
|
-
chatId: `cli-finance-${
|
|
82148
|
-
messageId: `cli-finance-message-${
|
|
82251
|
+
chatId: `cli-finance-${randomUUID15()}`,
|
|
82252
|
+
messageId: `cli-finance-message-${randomUUID15()}`,
|
|
82149
82253
|
apiKey: resolveApiKey(flags) ?? void 0,
|
|
82150
82254
|
promptInjectionProtection: false
|
|
82151
82255
|
});
|
|
@@ -82157,7 +82261,7 @@ async function handleFinance(client, subcommand, _rest, flags) {
|
|
|
82157
82261
|
}
|
|
82158
82262
|
function readFinanceCsvStatements(flags) {
|
|
82159
82263
|
const paths = parseCsvFlag(flags.csv) ?? [];
|
|
82160
|
-
return paths.map((filePath) => ({ filename:
|
|
82264
|
+
return paths.map((filePath) => ({ filename: basename4(filePath), content: readFileSync12(filePath, "utf8") }));
|
|
82161
82265
|
}
|
|
82162
82266
|
function buildFinanceCheckAccountsInput(flags, csvStatements, connectedAccount) {
|
|
82163
82267
|
const input = {
|
|
@@ -82452,7 +82556,7 @@ async function promptPlainText(question) {
|
|
|
82452
82556
|
}
|
|
82453
82557
|
async function writeSecretFile(filePath, content, force = false) {
|
|
82454
82558
|
const { mkdir: mkdir2, writeFile: writeFile2, stat: stat2 } = await import("fs/promises");
|
|
82455
|
-
const { dirname:
|
|
82559
|
+
const { dirname: dirname11 } = await import("path");
|
|
82456
82560
|
try {
|
|
82457
82561
|
await stat2(filePath);
|
|
82458
82562
|
if (!force) throw new Error(`${filePath} already exists. Use --force to overwrite.`);
|
|
@@ -82462,7 +82566,7 @@ async function writeSecretFile(filePath, content, force = false) {
|
|
|
82462
82566
|
}
|
|
82463
82567
|
if (error instanceof Error && !("code" in error)) throw error;
|
|
82464
82568
|
}
|
|
82465
|
-
await mkdir2(
|
|
82569
|
+
await mkdir2(dirname11(filePath), { recursive: true });
|
|
82466
82570
|
await writeFile2(filePath, content, { mode: 384 });
|
|
82467
82571
|
return filePath;
|
|
82468
82572
|
}
|
|
@@ -85628,12 +85732,16 @@ function printSelfUpdateHelp() {
|
|
|
85628
85732
|
openmates update [--version <version|tag>] [--package-manager <name>] [--dry-run] [--verbose] [--json]
|
|
85629
85733
|
openmates upgrade [--version <version|tag>] [--package-manager <name>] [--dry-run] [--verbose] [--json]
|
|
85630
85734
|
|
|
85631
|
-
Updates the globally installed openmates package
|
|
85735
|
+
Updates the globally installed openmates package using the saved release channel.
|
|
85736
|
+
Stable installations default to stable; prereleases default to dev.
|
|
85737
|
+
Channel changes persist only after a successful update or up-to-date check.
|
|
85632
85738
|
|
|
85633
85739
|
Options:
|
|
85634
|
-
--version <version|tag> Install a specific npm version or dist-tag (
|
|
85740
|
+
--version <version|tag> Install a specific npm version or dist-tag (one-time override)
|
|
85635
85741
|
--package-manager <name> npm, pnpm, yarn, or bun (default: detect, then npm)
|
|
85636
85742
|
--dry-run Print the package-manager command without running it
|
|
85743
|
+
--channel <dev|stable|main> Save release channel (dev uses npm alpha; stable/main uses latest)
|
|
85744
|
+
--allow-downgrade Explicitly allow installing an older version
|
|
85637
85745
|
--verbose Stream package-manager output during installation
|
|
85638
85746
|
--json Output the update plan/result as JSON`);
|
|
85639
85747
|
}
|
|
@@ -86440,7 +86548,7 @@ async function handleDocs(client, subcommand, rest, flags) {
|
|
|
86440
86548
|
}
|
|
86441
86549
|
if (subcommand === "download") {
|
|
86442
86550
|
const { writeFile: writeFile2, mkdir: mkdir2 } = await import("fs/promises");
|
|
86443
|
-
const { join:
|
|
86551
|
+
const { join: join12, dirname: dirname11 } = await import("path");
|
|
86444
86552
|
if (flags.all === true) {
|
|
86445
86553
|
const outputDir = typeof flags.output === "string" ? flags.output : "./openmates-docs";
|
|
86446
86554
|
const tree = await client.listDocs();
|
|
@@ -86449,8 +86557,8 @@ async function handleDocs(client, subcommand, rest, flags) {
|
|
|
86449
86557
|
let count = 0;
|
|
86450
86558
|
for (const slug2 of slugs) {
|
|
86451
86559
|
const content2 = await client.getDoc(slug2);
|
|
86452
|
-
const filePath =
|
|
86453
|
-
await mkdir2(
|
|
86560
|
+
const filePath = join12(outputDir, `${slug2}.md`);
|
|
86561
|
+
await mkdir2(dirname11(filePath), { recursive: true });
|
|
86454
86562
|
await writeFile2(filePath, content2, "utf-8");
|
|
86455
86563
|
count++;
|
|
86456
86564
|
process.stderr.write(`\r Downloaded ${count}/${slugs.length}`);
|
|
@@ -86522,8 +86630,8 @@ function isCliEntrypoint() {
|
|
|
86522
86630
|
if (!entrypoint) return false;
|
|
86523
86631
|
try {
|
|
86524
86632
|
const invokedPath = realpathSync2(entrypoint);
|
|
86525
|
-
const modulePath = realpathSync2(
|
|
86526
|
-
return invokedPath === modulePath ||
|
|
86633
|
+
const modulePath = realpathSync2(fileURLToPath3(import.meta.url));
|
|
86634
|
+
return invokedPath === modulePath || basename4(invokedPath) === "cli.js" && dirname10(invokedPath) === dirname10(modulePath);
|
|
86527
86635
|
} catch {
|
|
86528
86636
|
return false;
|
|
86529
86637
|
}
|
package/dist/cli.js
CHANGED
package/dist/index.js
CHANGED