openmates 0.11.0-alpha.16 → 0.11.0-alpha.17
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.
|
@@ -23,6 +23,49 @@ function getUploadOrigin(apiUrl) {
|
|
|
23
23
|
}
|
|
24
24
|
return "https://app.openmates.org";
|
|
25
25
|
}
|
|
26
|
+
function getUploadMimeType(filename) {
|
|
27
|
+
const ext = extname(filename).toLowerCase();
|
|
28
|
+
switch (ext) {
|
|
29
|
+
case ".jpg":
|
|
30
|
+
case ".jpeg":
|
|
31
|
+
return "image/jpeg";
|
|
32
|
+
case ".png":
|
|
33
|
+
return "image/png";
|
|
34
|
+
case ".webp":
|
|
35
|
+
return "image/webp";
|
|
36
|
+
case ".gif":
|
|
37
|
+
return "image/gif";
|
|
38
|
+
case ".heic":
|
|
39
|
+
return "image/heic";
|
|
40
|
+
case ".heif":
|
|
41
|
+
return "image/heif";
|
|
42
|
+
case ".bmp":
|
|
43
|
+
return "image/bmp";
|
|
44
|
+
case ".tif":
|
|
45
|
+
case ".tiff":
|
|
46
|
+
return "image/tiff";
|
|
47
|
+
case ".svg":
|
|
48
|
+
return "image/svg+xml";
|
|
49
|
+
case ".pdf":
|
|
50
|
+
return "application/pdf";
|
|
51
|
+
case ".mp3":
|
|
52
|
+
return "audio/mpeg";
|
|
53
|
+
case ".m4a":
|
|
54
|
+
case ".mp4":
|
|
55
|
+
return "audio/mp4";
|
|
56
|
+
case ".wav":
|
|
57
|
+
return "audio/wav";
|
|
58
|
+
case ".webm":
|
|
59
|
+
return "audio/webm";
|
|
60
|
+
case ".ogg":
|
|
61
|
+
case ".oga":
|
|
62
|
+
return "audio/ogg";
|
|
63
|
+
case ".aac":
|
|
64
|
+
return "audio/aac";
|
|
65
|
+
default:
|
|
66
|
+
return "application/octet-stream";
|
|
67
|
+
}
|
|
68
|
+
}
|
|
26
69
|
async function uploadFile(filePath, session) {
|
|
27
70
|
const filename = basename(filePath);
|
|
28
71
|
const fileBytes = readFileSync(filePath);
|
|
@@ -36,7 +79,7 @@ async function uploadFile(filePath, session) {
|
|
|
36
79
|
let lastError;
|
|
37
80
|
for (let attempt = 1; attempt <= UPLOAD_MAX_ATTEMPTS; attempt++) {
|
|
38
81
|
try {
|
|
39
|
-
const blob = new Blob([fileBytes]);
|
|
82
|
+
const blob = new Blob([fileBytes], { type: getUploadMimeType(filename) });
|
|
40
83
|
const formData = new FormData();
|
|
41
84
|
formData.append("file", blob, filename);
|
|
42
85
|
response = await fetch(uploadUrl, {
|
|
@@ -89,6 +132,73 @@ async function uploadFile(filePath, session) {
|
|
|
89
132
|
const data = await response.json();
|
|
90
133
|
return data;
|
|
91
134
|
}
|
|
135
|
+
async function transcribeUploadedAudio(uploadResult, filename, session, options = {}) {
|
|
136
|
+
const s3Key = uploadResult.files?.original?.s3_key ?? Object.values(uploadResult.files ?? {})[0]?.s3_key;
|
|
137
|
+
if (!s3Key) {
|
|
138
|
+
throw new Error("Upload succeeded but no audio file key was returned.");
|
|
139
|
+
}
|
|
140
|
+
const cookies = [];
|
|
141
|
+
if (session.cookies?.auth_refresh_token) {
|
|
142
|
+
cookies.push(`auth_refresh_token=${session.cookies.auth_refresh_token}`);
|
|
143
|
+
}
|
|
144
|
+
const requestItem = {
|
|
145
|
+
id: options.requestId ?? uploadResult.embed_id,
|
|
146
|
+
embed_id: uploadResult.embed_id,
|
|
147
|
+
s3_key: s3Key,
|
|
148
|
+
s3_base_url: uploadResult.s3_base_url,
|
|
149
|
+
aes_key: uploadResult.aes_key,
|
|
150
|
+
aes_nonce: uploadResult.aes_nonce,
|
|
151
|
+
vault_wrapped_aes_key: uploadResult.vault_wrapped_aes_key,
|
|
152
|
+
filename,
|
|
153
|
+
mime_type: uploadResult.content_type
|
|
154
|
+
};
|
|
155
|
+
if (options.chatId) {
|
|
156
|
+
requestItem.chat_id = options.chatId;
|
|
157
|
+
}
|
|
158
|
+
const response = await fetch(
|
|
159
|
+
`${session.apiUrl.replace(/\/$/, "")}/v1/apps/audio/skills/transcribe`,
|
|
160
|
+
{
|
|
161
|
+
method: "POST",
|
|
162
|
+
headers: {
|
|
163
|
+
Accept: "application/json",
|
|
164
|
+
"Content-Type": "application/json",
|
|
165
|
+
...cookies.length > 0 ? { Cookie: cookies.join("; ") } : {}
|
|
166
|
+
},
|
|
167
|
+
body: JSON.stringify({ requests: [requestItem] }),
|
|
168
|
+
signal: AbortSignal.timeout(10 * 60 * 1e3)
|
|
169
|
+
}
|
|
170
|
+
);
|
|
171
|
+
if (!response.ok) {
|
|
172
|
+
let detail = `Transcription failed (HTTP ${response.status}).`;
|
|
173
|
+
try {
|
|
174
|
+
const data2 = await response.json();
|
|
175
|
+
detail = data2.detail ?? data2.error ?? detail;
|
|
176
|
+
} catch {
|
|
177
|
+
}
|
|
178
|
+
throw new Error(detail);
|
|
179
|
+
}
|
|
180
|
+
const data = await response.json();
|
|
181
|
+
if (data.success === false) {
|
|
182
|
+
throw new Error(data.error ?? "Transcription failed.");
|
|
183
|
+
}
|
|
184
|
+
const requestId = options.requestId ?? uploadResult.embed_id;
|
|
185
|
+
const group = data.data?.results?.find((item) => item.id === requestId) ?? data.data?.results?.[0];
|
|
186
|
+
const result = group?.results?.[0];
|
|
187
|
+
if (!result) {
|
|
188
|
+
throw new Error(group?.error ?? "Transcription response did not include a result.");
|
|
189
|
+
}
|
|
190
|
+
if (result.error) {
|
|
191
|
+
throw new Error(result.error);
|
|
192
|
+
}
|
|
193
|
+
return {
|
|
194
|
+
transcript: result.transcript ?? null,
|
|
195
|
+
transcript_original: result.transcript_original ?? null,
|
|
196
|
+
transcript_corrected: result.transcript_corrected ?? null,
|
|
197
|
+
use_corrected: result.use_corrected ?? null,
|
|
198
|
+
correction_model: result.correction_model ?? null,
|
|
199
|
+
model: result.model ?? null
|
|
200
|
+
};
|
|
201
|
+
}
|
|
92
202
|
function getProfileImageMime(filename) {
|
|
93
203
|
const ext = extname(filename).toLowerCase();
|
|
94
204
|
if (ext === ".jpg" || ext === ".jpeg") return "image/jpeg";
|
|
@@ -127,5 +237,6 @@ async function uploadProfileImage(filePath, session) {
|
|
|
127
237
|
|
|
128
238
|
export {
|
|
129
239
|
uploadFile,
|
|
240
|
+
transcribeUploadedAudio,
|
|
130
241
|
uploadProfileImage
|
|
131
242
|
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
|
+
transcribeUploadedAudio,
|
|
2
3
|
uploadFile
|
|
3
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-AXNRPVLE.js";
|
|
4
5
|
|
|
5
6
|
// src/client.ts
|
|
6
7
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
@@ -2687,6 +2688,15 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
2687
2688
|
}
|
|
2688
2689
|
}
|
|
2689
2690
|
}
|
|
2691
|
+
if (params.preparedEmbeds && params.preparedEmbeds.length > 0) {
|
|
2692
|
+
messagePayload.embeds = params.preparedEmbeds.map((embed) => ({
|
|
2693
|
+
embed_id: embed.embedId,
|
|
2694
|
+
type: embed.type,
|
|
2695
|
+
content: embed.content,
|
|
2696
|
+
status: embed.status,
|
|
2697
|
+
text_preview: embed.textPreview
|
|
2698
|
+
}));
|
|
2699
|
+
}
|
|
2690
2700
|
const encryptedEmbeds = [...params.encryptedEmbeds ?? []];
|
|
2691
2701
|
if (!params.incognito && params.preparedEmbeds && params.preparedEmbeds.length > 0) {
|
|
2692
2702
|
const masterKey = this.getMasterKeyBytes();
|
|
@@ -3328,7 +3338,7 @@ var OpenMatesClient = class _OpenMatesClient {
|
|
|
3328
3338
|
return this.settingsPost("user/username", { username });
|
|
3329
3339
|
}
|
|
3330
3340
|
async updateProfileImage(filePath) {
|
|
3331
|
-
const { uploadProfileImage } = await import("./uploadService-
|
|
3341
|
+
const { uploadProfileImage } = await import("./uploadService-S464XJRA.js");
|
|
3332
3342
|
const result = await uploadProfileImage(filePath, this.requireSession());
|
|
3333
3343
|
if (result.status === "rejected") {
|
|
3334
3344
|
throw new Error(result.detail ?? "Profile image rejected by content safety checks.");
|
|
@@ -5100,6 +5110,16 @@ var IMAGE_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
|
5100
5110
|
"tif",
|
|
5101
5111
|
"svg"
|
|
5102
5112
|
]);
|
|
5113
|
+
var AUDIO_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
5114
|
+
"mp3",
|
|
5115
|
+
"m4a",
|
|
5116
|
+
"mp4",
|
|
5117
|
+
"wav",
|
|
5118
|
+
"webm",
|
|
5119
|
+
"ogg",
|
|
5120
|
+
"oga",
|
|
5121
|
+
"aac"
|
|
5122
|
+
]);
|
|
5103
5123
|
function isEnvFile(filename) {
|
|
5104
5124
|
const lower = filename.toLowerCase();
|
|
5105
5125
|
return lower === ".env" || lower.startsWith(".env.") || lower === ".envrc";
|
|
@@ -5120,6 +5140,9 @@ function isImageFile(filename) {
|
|
|
5120
5140
|
function isPDFFile(filename) {
|
|
5121
5141
|
return getExt(filename) === "pdf";
|
|
5122
5142
|
}
|
|
5143
|
+
function isAudioFile(filename) {
|
|
5144
|
+
return AUDIO_EXTENSIONS.has(getExt(filename));
|
|
5145
|
+
}
|
|
5123
5146
|
var LANGUAGE_MAP = {
|
|
5124
5147
|
ts: "typescript",
|
|
5125
5148
|
tsx: "typescript",
|
|
@@ -5264,10 +5287,14 @@ function processFiles(filePaths, redactor) {
|
|
|
5264
5287
|
const result = processPDFFile(resolvedPath, filename);
|
|
5265
5288
|
if (result) embeds.push(result);
|
|
5266
5289
|
else errors.push({ path: rawPath, error: "Failed to process PDF" });
|
|
5290
|
+
} else if (isAudioFile(filename)) {
|
|
5291
|
+
const result = processAudioFile(resolvedPath, filename);
|
|
5292
|
+
if (result) embeds.push(result);
|
|
5293
|
+
else errors.push({ path: rawPath, error: "Failed to process audio" });
|
|
5267
5294
|
} else {
|
|
5268
5295
|
errors.push({
|
|
5269
5296
|
path: rawPath,
|
|
5270
|
-
error: `Unsupported file type: .${ext}. Supported: code/text, images, PDFs.`
|
|
5297
|
+
error: `Unsupported file type: .${ext}. Supported: code/text, images, PDFs, audio.`
|
|
5271
5298
|
});
|
|
5272
5299
|
}
|
|
5273
5300
|
}
|
|
@@ -5396,6 +5423,40 @@ function processPDFFile(filePath, filename) {
|
|
|
5396
5423
|
return null;
|
|
5397
5424
|
}
|
|
5398
5425
|
}
|
|
5426
|
+
function processAudioFile(filePath, filename) {
|
|
5427
|
+
try {
|
|
5428
|
+
const embedId = generateEmbedId();
|
|
5429
|
+
const embedContent = toonEncodeContent({
|
|
5430
|
+
app_id: "audio",
|
|
5431
|
+
skill_id: "transcribe",
|
|
5432
|
+
type: "audio-recording",
|
|
5433
|
+
status: "uploading",
|
|
5434
|
+
filename
|
|
5435
|
+
});
|
|
5436
|
+
const embed = {
|
|
5437
|
+
embedId,
|
|
5438
|
+
type: "audio-recording",
|
|
5439
|
+
content: embedContent,
|
|
5440
|
+
textPreview: filename,
|
|
5441
|
+
status: "processing"
|
|
5442
|
+
};
|
|
5443
|
+
return {
|
|
5444
|
+
embed,
|
|
5445
|
+
referenceBlock: createEmbedReferenceBlock("audio-recording", embedId),
|
|
5446
|
+
displayName: filename,
|
|
5447
|
+
secretsRedacted: false,
|
|
5448
|
+
zeroKnowledge: false,
|
|
5449
|
+
requiresUpload: true,
|
|
5450
|
+
localPath: filePath
|
|
5451
|
+
};
|
|
5452
|
+
} catch (e) {
|
|
5453
|
+
process.stderr.write(
|
|
5454
|
+
`\x1B[31mError:\x1B[0m Failed to process ${filename}: ${e instanceof Error ? e.message : String(e)}
|
|
5455
|
+
`
|
|
5456
|
+
);
|
|
5457
|
+
return null;
|
|
5458
|
+
}
|
|
5459
|
+
}
|
|
5399
5460
|
function formatEmbedsForMessage(embeds) {
|
|
5400
5461
|
if (embeds.length === 0) return "";
|
|
5401
5462
|
return "\n" + embeds.map((e) => e.referenceBlock).join("\n");
|
|
@@ -6514,7 +6575,8 @@ function formatTs(ts) {
|
|
|
6514
6575
|
|
|
6515
6576
|
// src/server.ts
|
|
6516
6577
|
import { execSync, spawn as nodeSpawn } from "child_process";
|
|
6517
|
-
import {
|
|
6578
|
+
import { randomBytes as randomBytes2 } from "crypto";
|
|
6579
|
+
import { copyFileSync, existsSync as existsSync5, mkdirSync as mkdirSync3, readFileSync as readFileSync5, rmSync as rmSync3, writeFileSync as writeFileSync3 } from "fs";
|
|
6518
6580
|
import { createInterface as createInterface2 } from "readline";
|
|
6519
6581
|
import { homedir as homedir5 } from "os";
|
|
6520
6582
|
import { join as join3, resolve as resolve3 } from "path";
|
|
@@ -6552,16 +6614,17 @@ function removeServerConfig() {
|
|
|
6552
6614
|
rmSync2(filePath);
|
|
6553
6615
|
}
|
|
6554
6616
|
}
|
|
6555
|
-
var
|
|
6617
|
+
var SOURCE_COMPOSE_MARKER = join2("backend", "core", "docker-compose.yml");
|
|
6618
|
+
var IMAGE_COMPOSE_MARKER = join2("backend", "core", "docker-compose.selfhost.yml");
|
|
6556
6619
|
function isOpenMatesDir(dir) {
|
|
6557
|
-
return existsSync4(join2(dir,
|
|
6620
|
+
return existsSync4(join2(dir, SOURCE_COMPOSE_MARKER)) || existsSync4(join2(dir, IMAGE_COMPOSE_MARKER));
|
|
6558
6621
|
}
|
|
6559
6622
|
function resolveServerPath(flags) {
|
|
6560
6623
|
if (typeof flags.path === "string" && flags.path) {
|
|
6561
6624
|
const explicit = resolve2(flags.path);
|
|
6562
6625
|
if (!isOpenMatesDir(explicit)) {
|
|
6563
6626
|
throw new Error(
|
|
6564
|
-
`${explicit} does not appear to be an OpenMates installation (missing ${
|
|
6627
|
+
`${explicit} does not appear to be an OpenMates installation (missing ${SOURCE_COMPOSE_MARKER} or ${IMAGE_COMPOSE_MARKER}).`
|
|
6565
6628
|
);
|
|
6566
6629
|
}
|
|
6567
6630
|
return explicit;
|
|
@@ -6580,11 +6643,67 @@ function resolveServerPath(flags) {
|
|
|
6580
6643
|
}
|
|
6581
6644
|
|
|
6582
6645
|
// src/server.ts
|
|
6583
|
-
var
|
|
6646
|
+
var SOURCE_COMPOSE_FILE = join3("backend", "core", "docker-compose.yml");
|
|
6647
|
+
var IMAGE_COMPOSE_FILE = join3("backend", "core", "docker-compose.selfhost.yml");
|
|
6584
6648
|
var COMPOSE_OVERRIDE = join3("backend", "core", "docker-compose.override.yml");
|
|
6585
6649
|
var DEFAULT_INSTALL_PATH = join3(homedir5(), "openmates");
|
|
6586
6650
|
var REPO_URL = "https://github.com/glowingkitty/OpenMates.git";
|
|
6587
6651
|
var DEV_BRANCH = "dev";
|
|
6652
|
+
var DEFAULT_IMAGE_REGISTRY = "ghcr.io/glowingkitty";
|
|
6653
|
+
var MINIMAL_ENV_TEMPLATE = `# OpenMates self-host image-mode environment
|
|
6654
|
+
SECRET__MISTRAL_AI__API_KEY=
|
|
6655
|
+
SECRET__CEREBRAS__API_KEY=
|
|
6656
|
+
SECRET__GROQ__API_KEY=
|
|
6657
|
+
SECRET__OPENAI__API_KEY=
|
|
6658
|
+
SECRET__ANTHROPIC__API_KEY=
|
|
6659
|
+
SECRET__GOOGLE_AI_STUDIO__API_KEY=
|
|
6660
|
+
SECRET__OPENROUTER__API_KEY=
|
|
6661
|
+
SECRET__TOGETHER__API_KEY=
|
|
6662
|
+
SECRET__BRAVE__API_KEY=
|
|
6663
|
+
SECRET__FIRECRAWL__API_KEY=
|
|
6664
|
+
SECRET__CONTEXT7__API_KEY=
|
|
6665
|
+
DATABASE_ADMIN_EMAIL=admin@example.com
|
|
6666
|
+
DATABASE_ADMIN_PASSWORD=
|
|
6667
|
+
DATABASE_NAME=directus
|
|
6668
|
+
DATABASE_USERNAME=directus
|
|
6669
|
+
DATABASE_PASSWORD=
|
|
6670
|
+
DIRECTUS_TOKEN=
|
|
6671
|
+
DIRECTUS_SECRET=
|
|
6672
|
+
DRAGONFLY_PASSWORD=
|
|
6673
|
+
OPENOBSERVE_ROOT_EMAIL=admin@openmates.internal
|
|
6674
|
+
OPENOBSERVE_ROOT_PASSWORD=
|
|
6675
|
+
INTERNAL_API_SHARED_TOKEN=
|
|
6676
|
+
TUNNEL_TRIGGER_SECRET=<PLACEHOLDER>
|
|
6677
|
+
SERVER_ENVIRONMENT=production
|
|
6678
|
+
FRONTEND_URLS="http://localhost:5173"
|
|
6679
|
+
TRUSTED_PROXY_IPS="172.16.0.0/12"
|
|
6680
|
+
CORE_SIDECAR_URL=http://admin-sidecar:8001
|
|
6681
|
+
CLEAR_CACHE_ON_UPDATE=true
|
|
6682
|
+
SIGNUP_LIMIT=20
|
|
6683
|
+
SELF_HOST_SIGNUP_MODE=invite_only
|
|
6684
|
+
SELF_HOST_SIGNUP_ALLOWED_DOMAINS=
|
|
6685
|
+
SELF_HOST_FIRST_INVITE_CODE=
|
|
6686
|
+
APPLICATION_PREVIEW_ORIGIN=
|
|
6687
|
+
OPENMATES_IMAGE_REGISTRY=${DEFAULT_IMAGE_REGISTRY}
|
|
6688
|
+
OPENMATES_IMAGE_TAG=
|
|
6689
|
+
GIT_WORK_DIR=
|
|
6690
|
+
DOCKER_GID=999
|
|
6691
|
+
`;
|
|
6692
|
+
var VAULT_CONFIG_TEMPLATE = `# Minimal Vault configuration
|
|
6693
|
+
listener "tcp" {
|
|
6694
|
+
address = "0.0.0.0:8200"
|
|
6695
|
+
tls_disable = true
|
|
6696
|
+
}
|
|
6697
|
+
|
|
6698
|
+
storage "file" {
|
|
6699
|
+
path = "/vault/file"
|
|
6700
|
+
}
|
|
6701
|
+
|
|
6702
|
+
api_addr = "http://0.0.0.0:8200"
|
|
6703
|
+
ui = false
|
|
6704
|
+
disable_mlock = true
|
|
6705
|
+
log_level = "info"
|
|
6706
|
+
`;
|
|
6588
6707
|
var LLM_PROVIDER_ENV_KEYS = /* @__PURE__ */ new Set([
|
|
6589
6708
|
"SECRET__MISTRAL_AI__API_KEY",
|
|
6590
6709
|
"SECRET__CEREBRAS__API_KEY",
|
|
@@ -6605,8 +6724,21 @@ function runInteractive(cmd, args, cwd) {
|
|
|
6605
6724
|
child.on("error", reject);
|
|
6606
6725
|
});
|
|
6607
6726
|
}
|
|
6608
|
-
function
|
|
6609
|
-
const
|
|
6727
|
+
function loadConfigForInstallPath(installPath) {
|
|
6728
|
+
const config = loadServerConfig();
|
|
6729
|
+
return config?.installPath === installPath ? config : null;
|
|
6730
|
+
}
|
|
6731
|
+
function getInstallMode(installPath, config = loadConfigForInstallPath(installPath)) {
|
|
6732
|
+
if (config?.installMode) return config.installMode;
|
|
6733
|
+
if (existsSync5(join3(installPath, IMAGE_COMPOSE_FILE))) return "image";
|
|
6734
|
+
return "source";
|
|
6735
|
+
}
|
|
6736
|
+
function shouldPullImages() {
|
|
6737
|
+
return process.env.OPENMATES_SKIP_IMAGE_PULL !== "1";
|
|
6738
|
+
}
|
|
6739
|
+
function composeArgs(installPath, withOverrides, installMode = getInstallMode(installPath)) {
|
|
6740
|
+
const composeFile = installMode === "image" ? IMAGE_COMPOSE_FILE : SOURCE_COMPOSE_FILE;
|
|
6741
|
+
const args = ["compose", "--env-file", ".env", "-f", composeFile];
|
|
6610
6742
|
if (withOverrides && existsSync5(join3(installPath, COMPOSE_OVERRIDE))) {
|
|
6611
6743
|
args.push("-f", COMPOSE_OVERRIDE);
|
|
6612
6744
|
}
|
|
@@ -6651,6 +6783,80 @@ function getPackageVersion() {
|
|
|
6651
6783
|
return "";
|
|
6652
6784
|
}
|
|
6653
6785
|
}
|
|
6786
|
+
function getDefaultImageTag() {
|
|
6787
|
+
const version = getPackageVersion();
|
|
6788
|
+
return version ? `v${version}` : "dev";
|
|
6789
|
+
}
|
|
6790
|
+
function defaultTemplateRefForVersion(version) {
|
|
6791
|
+
return /-(alpha|beta|rc)(\.|\d|$)/.test(version) ? DEV_BRANCH : `v${version}`;
|
|
6792
|
+
}
|
|
6793
|
+
function randomHex(bytes) {
|
|
6794
|
+
return randomBytes2(bytes).toString("hex");
|
|
6795
|
+
}
|
|
6796
|
+
function generateInviteCode() {
|
|
6797
|
+
const digits = Array.from(randomBytes2(12), (byte) => String(byte % 10)).join("");
|
|
6798
|
+
return `${digits.slice(0, 4)}-${digits.slice(4, 8)}-${digits.slice(8, 12)}`;
|
|
6799
|
+
}
|
|
6800
|
+
function getEnvVar(content, name) {
|
|
6801
|
+
const match = content.match(new RegExp(`^${name}=(.*)$`, "m"));
|
|
6802
|
+
return match?.[1]?.replace(/^"|"$/g, "") ?? "";
|
|
6803
|
+
}
|
|
6804
|
+
function setEnvVar(content, name, value) {
|
|
6805
|
+
const line = `${name}=${value}`;
|
|
6806
|
+
const pattern = new RegExp(`^${name}=.*$`, "m");
|
|
6807
|
+
if (pattern.test(content)) {
|
|
6808
|
+
return content.replace(pattern, line);
|
|
6809
|
+
}
|
|
6810
|
+
const separator = content.endsWith("\n") ? "" : "\n";
|
|
6811
|
+
return `${content}${separator}${line}
|
|
6812
|
+
`;
|
|
6813
|
+
}
|
|
6814
|
+
function setEnvIfEmpty(content, name, value) {
|
|
6815
|
+
return getEnvVar(content, name) ? content : setEnvVar(content, name, value);
|
|
6816
|
+
}
|
|
6817
|
+
async function fetchText(url) {
|
|
6818
|
+
const response = await fetch(url);
|
|
6819
|
+
if (!response.ok) {
|
|
6820
|
+
throw new Error(`Failed to download ${url}: HTTP ${response.status}`);
|
|
6821
|
+
}
|
|
6822
|
+
return response.text();
|
|
6823
|
+
}
|
|
6824
|
+
async function loadSelfHostComposeTemplate(version) {
|
|
6825
|
+
const templateDir = process.env.OPENMATES_SELFHOST_TEMPLATE_DIR;
|
|
6826
|
+
if (templateDir) {
|
|
6827
|
+
return readFileSync5(join3(resolve3(templateDir), IMAGE_COMPOSE_FILE), "utf-8");
|
|
6828
|
+
}
|
|
6829
|
+
const overrideUrl = process.env.OPENMATES_SELFHOST_COMPOSE_URL;
|
|
6830
|
+
if (overrideUrl) {
|
|
6831
|
+
return fetchText(overrideUrl);
|
|
6832
|
+
}
|
|
6833
|
+
const ref = defaultTemplateRefForVersion(version);
|
|
6834
|
+
return fetchText(
|
|
6835
|
+
`https://raw.githubusercontent.com/glowingkitty/OpenMates/${ref}/backend/core/docker-compose.selfhost.yml`
|
|
6836
|
+
);
|
|
6837
|
+
}
|
|
6838
|
+
async function writeImageModeRuntimeFiles(installPath, imageTag) {
|
|
6839
|
+
const coreDir = join3(installPath, "backend", "core");
|
|
6840
|
+
const vaultConfigDir = join3(coreDir, "vault", "config");
|
|
6841
|
+
mkdirSync3(vaultConfigDir, { recursive: true });
|
|
6842
|
+
writeFileSync3(join3(coreDir, "docker-compose.selfhost.yml"), await loadSelfHostComposeTemplate(getPackageVersion()));
|
|
6843
|
+
writeFileSync3(join3(vaultConfigDir, "vault.hcl"), VAULT_CONFIG_TEMPLATE);
|
|
6844
|
+
const envPath = join3(installPath, ".env");
|
|
6845
|
+
let envContent = existsSync5(envPath) ? readFileSync5(envPath, "utf-8") : MINIMAL_ENV_TEMPLATE;
|
|
6846
|
+
envContent = setEnvIfEmpty(envContent, "DATABASE_ADMIN_PASSWORD", randomHex(12));
|
|
6847
|
+
envContent = setEnvIfEmpty(envContent, "DATABASE_PASSWORD", randomHex(12));
|
|
6848
|
+
envContent = setEnvIfEmpty(envContent, "DIRECTUS_TOKEN", randomHex(32));
|
|
6849
|
+
envContent = setEnvIfEmpty(envContent, "DIRECTUS_SECRET", randomHex(32));
|
|
6850
|
+
envContent = setEnvIfEmpty(envContent, "DRAGONFLY_PASSWORD", randomHex(12));
|
|
6851
|
+
envContent = setEnvIfEmpty(envContent, "OPENOBSERVE_ROOT_PASSWORD", randomHex(32));
|
|
6852
|
+
envContent = setEnvIfEmpty(envContent, "INTERNAL_API_SHARED_TOKEN", randomHex(32));
|
|
6853
|
+
envContent = setEnvIfEmpty(envContent, "SELF_HOST_FIRST_INVITE_CODE", generateInviteCode());
|
|
6854
|
+
envContent = setEnvVar(envContent, "OPENMATES_IMAGE_TAG", imageTag);
|
|
6855
|
+
envContent = setEnvVar(envContent, "OPENMATES_IMAGE_REGISTRY", DEFAULT_IMAGE_REGISTRY);
|
|
6856
|
+
envContent = setEnvVar(envContent, "GIT_WORK_DIR", installPath);
|
|
6857
|
+
writeFileSync3(envPath, envContent.endsWith("\n") ? envContent : `${envContent}
|
|
6858
|
+
`);
|
|
6859
|
+
}
|
|
6654
6860
|
function defaultCloneBranchForVersion(version) {
|
|
6655
6861
|
return /-(alpha|beta|rc)(\.|\d|$)/.test(version) ? DEV_BRANCH : null;
|
|
6656
6862
|
}
|
|
@@ -6700,9 +6906,9 @@ async function serverStatus(flags) {
|
|
|
6700
6906
|
requireDocker();
|
|
6701
6907
|
const installPath = resolveServerPath(flags);
|
|
6702
6908
|
ensureGitWorkDirEnv(installPath);
|
|
6703
|
-
const config =
|
|
6909
|
+
const config = loadConfigForInstallPath(installPath);
|
|
6704
6910
|
const withOverrides = config?.composeProfile === "full";
|
|
6705
|
-
const args = [...composeArgs(installPath, withOverrides), "ps"];
|
|
6911
|
+
const args = [...composeArgs(installPath, withOverrides, getInstallMode(installPath, config)), "ps"];
|
|
6706
6912
|
if (flags.json === true) {
|
|
6707
6913
|
args.push("--format", "json");
|
|
6708
6914
|
}
|
|
@@ -6715,13 +6921,20 @@ async function serverStart(flags) {
|
|
|
6715
6921
|
ensureGitWorkDirEnv(installPath);
|
|
6716
6922
|
warnIfMissingLlmCredentials(installPath);
|
|
6717
6923
|
const withOverrides = flags["with-overrides"] === true;
|
|
6718
|
-
const
|
|
6719
|
-
const
|
|
6924
|
+
const config = loadConfigForInstallPath(installPath);
|
|
6925
|
+
const installMode = getInstallMode(installPath, config);
|
|
6926
|
+
const pullArgs = [...composeArgs(installPath, withOverrides, installMode), "pull"];
|
|
6927
|
+
const args = [...composeArgs(installPath, withOverrides, installMode), "up", "-d"];
|
|
6720
6928
|
if (config && withOverrides && config.composeProfile !== "full") {
|
|
6721
6929
|
saveServerConfig({ ...config, composeProfile: "full" });
|
|
6722
6930
|
}
|
|
6723
6931
|
console.error("Starting OpenMates server...");
|
|
6724
|
-
|
|
6932
|
+
let code = 0;
|
|
6933
|
+
if (installMode === "image" && shouldPullImages()) {
|
|
6934
|
+
code = await runInteractive("docker", pullArgs, installPath);
|
|
6935
|
+
if (code !== 0) process.exit(code);
|
|
6936
|
+
}
|
|
6937
|
+
code = await runInteractive("docker", args, installPath);
|
|
6725
6938
|
if (code !== 0) process.exit(code);
|
|
6726
6939
|
if (flags.json === true) {
|
|
6727
6940
|
printJson({ command: "start", status: "success", path: installPath });
|
|
@@ -6739,9 +6952,9 @@ async function serverStop(flags) {
|
|
|
6739
6952
|
requireDocker();
|
|
6740
6953
|
const installPath = resolveServerPath(flags);
|
|
6741
6954
|
ensureGitWorkDirEnv(installPath);
|
|
6742
|
-
const config =
|
|
6955
|
+
const config = loadConfigForInstallPath(installPath);
|
|
6743
6956
|
const withOverrides = config?.composeProfile === "full";
|
|
6744
|
-
const args = [...composeArgs(installPath, withOverrides), "down"];
|
|
6957
|
+
const args = [...composeArgs(installPath, withOverrides, getInstallMode(installPath, config)), "down"];
|
|
6745
6958
|
console.error("Stopping OpenMates server...");
|
|
6746
6959
|
const code = await runInteractive("docker", args, installPath);
|
|
6747
6960
|
if (code !== 0) process.exit(code);
|
|
@@ -6755,26 +6968,32 @@ async function serverRestart(flags) {
|
|
|
6755
6968
|
requireDocker();
|
|
6756
6969
|
const installPath = resolveServerPath(flags);
|
|
6757
6970
|
ensureGitWorkDirEnv(installPath);
|
|
6758
|
-
const config =
|
|
6971
|
+
const config = loadConfigForInstallPath(installPath);
|
|
6759
6972
|
const withOverrides = config?.composeProfile === "full";
|
|
6973
|
+
const installMode = getInstallMode(installPath, config);
|
|
6760
6974
|
if (flags.rebuild === true) {
|
|
6975
|
+
if (installMode === "image") {
|
|
6976
|
+
throw new Error(
|
|
6977
|
+
"Image-mode installs use prebuilt images and cannot rebuild locally. Run 'openmates server update' to pull newer images, or reinstall with --from-source to build from source."
|
|
6978
|
+
);
|
|
6979
|
+
}
|
|
6761
6980
|
console.error("Rebuilding OpenMates server (this may take a few minutes)...");
|
|
6762
|
-
const downArgs = [...composeArgs(installPath, withOverrides), "down"];
|
|
6981
|
+
const downArgs = [...composeArgs(installPath, withOverrides, installMode), "down"];
|
|
6763
6982
|
let code = await runInteractive("docker", downArgs, installPath);
|
|
6764
6983
|
if (code !== 0) process.exit(code);
|
|
6765
6984
|
try {
|
|
6766
6985
|
exec("docker volume rm openmates-cache-data", installPath);
|
|
6767
6986
|
} catch {
|
|
6768
6987
|
}
|
|
6769
|
-
const buildArgs = [...composeArgs(installPath, withOverrides), "build"];
|
|
6988
|
+
const buildArgs = [...composeArgs(installPath, withOverrides, installMode), "build"];
|
|
6770
6989
|
code = await runInteractive("docker", buildArgs, installPath);
|
|
6771
6990
|
if (code !== 0) process.exit(code);
|
|
6772
|
-
const upArgs = [...composeArgs(installPath, withOverrides), "up", "-d"];
|
|
6991
|
+
const upArgs = [...composeArgs(installPath, withOverrides, installMode), "up", "-d"];
|
|
6773
6992
|
code = await runInteractive("docker", upArgs, installPath);
|
|
6774
6993
|
if (code !== 0) process.exit(code);
|
|
6775
6994
|
} else {
|
|
6776
6995
|
console.error("Restarting OpenMates server...");
|
|
6777
|
-
const args = [...composeArgs(installPath, withOverrides), "restart"];
|
|
6996
|
+
const args = [...composeArgs(installPath, withOverrides, installMode), "restart"];
|
|
6778
6997
|
const code = await runInteractive("docker", args, installPath);
|
|
6779
6998
|
if (code !== 0) process.exit(code);
|
|
6780
6999
|
}
|
|
@@ -6788,9 +7007,9 @@ async function serverLogs(flags) {
|
|
|
6788
7007
|
requireDocker();
|
|
6789
7008
|
const installPath = resolveServerPath(flags);
|
|
6790
7009
|
ensureGitWorkDirEnv(installPath);
|
|
6791
|
-
const config =
|
|
7010
|
+
const config = loadConfigForInstallPath(installPath);
|
|
6792
7011
|
const withOverrides = config?.composeProfile === "full";
|
|
6793
|
-
const args = [...composeArgs(installPath, withOverrides), "logs"];
|
|
7012
|
+
const args = [...composeArgs(installPath, withOverrides, getInstallMode(installPath, config)), "logs"];
|
|
6794
7013
|
if (flags.follow === true || flags.f === true) {
|
|
6795
7014
|
args.push("--follow");
|
|
6796
7015
|
}
|
|
@@ -6808,14 +7027,56 @@ async function serverLogs(flags) {
|
|
|
6808
7027
|
if (code !== 0) process.exit(code);
|
|
6809
7028
|
}
|
|
6810
7029
|
async function serverInstall(flags) {
|
|
6811
|
-
requireGit();
|
|
6812
7030
|
const installPath = typeof flags.path === "string" ? resolve3(flags.path) : DEFAULT_INSTALL_PATH;
|
|
6813
7031
|
const sourcePath = typeof flags["source-path"] === "string" ? resolve3(flags["source-path"]) : null;
|
|
6814
|
-
|
|
7032
|
+
const fromSource = flags["from-source"] === true || sourcePath !== null;
|
|
7033
|
+
if (existsSync5(join3(installPath, SOURCE_COMPOSE_FILE)) || existsSync5(join3(installPath, IMAGE_COMPOSE_FILE))) {
|
|
6815
7034
|
console.error(`OpenMates already exists at ${installPath}.`);
|
|
6816
7035
|
console.error("Use 'openmates server update' to update, or choose a different --path.");
|
|
6817
7036
|
process.exit(1);
|
|
6818
7037
|
}
|
|
7038
|
+
if (!fromSource) {
|
|
7039
|
+
requireDocker();
|
|
7040
|
+
mkdirSync3(installPath, { recursive: true });
|
|
7041
|
+
if (typeof flags["env-path"] === "string") {
|
|
7042
|
+
const envSource = resolve3(flags["env-path"]);
|
|
7043
|
+
if (!existsSync5(envSource)) {
|
|
7044
|
+
throw new Error(`Env file not found: ${envSource}`);
|
|
7045
|
+
}
|
|
7046
|
+
copyFileSync(envSource, join3(installPath, ".env"));
|
|
7047
|
+
console.error(`Copied ${envSource} to ${installPath}/.env`);
|
|
7048
|
+
}
|
|
7049
|
+
const imageTag = typeof flags["image-tag"] === "string" ? flags["image-tag"] : getDefaultImageTag();
|
|
7050
|
+
console.error(`Preparing OpenMates image-mode install at ${installPath}...`);
|
|
7051
|
+
await writeImageModeRuntimeFiles(installPath, imageTag);
|
|
7052
|
+
try {
|
|
7053
|
+
exec("docker network create openmates", installPath);
|
|
7054
|
+
} catch {
|
|
7055
|
+
}
|
|
7056
|
+
saveServerConfig({
|
|
7057
|
+
installPath,
|
|
7058
|
+
installedAt: Date.now(),
|
|
7059
|
+
composeProfile: "core",
|
|
7060
|
+
installMode: "image",
|
|
7061
|
+
imageTag
|
|
7062
|
+
});
|
|
7063
|
+
if (flags.json === true) {
|
|
7064
|
+
printJson({ command: "install", status: "success", path: installPath, mode: "image", imageTag });
|
|
7065
|
+
} else {
|
|
7066
|
+
const firstInvite = getEnvVar(readFileSync5(join3(installPath, ".env"), "utf-8"), "SELF_HOST_FIRST_INVITE_CODE");
|
|
7067
|
+
console.log(`
|
|
7068
|
+
OpenMates installed at ${installPath}`);
|
|
7069
|
+
console.log(`Mode: image (${DEFAULT_IMAGE_REGISTRY}, tag ${imageTag})`);
|
|
7070
|
+
console.log("\nNext steps:");
|
|
7071
|
+
console.log(" 1. Run: openmates server start");
|
|
7072
|
+
console.log(" 2. Open http://localhost:5173");
|
|
7073
|
+
if (firstInvite) console.log(` 3. Sign up with invite code: ${firstInvite}`);
|
|
7074
|
+
console.log(" 4. After signup, make yourself admin: openmates server make-admin your@email.com");
|
|
7075
|
+
console.log("\nOptional: edit .env first to add LLM provider API keys. Source builds are available with --from-source.");
|
|
7076
|
+
}
|
|
7077
|
+
return;
|
|
7078
|
+
}
|
|
7079
|
+
requireGit();
|
|
6819
7080
|
const cloneSource = sourcePath ?? REPO_URL;
|
|
6820
7081
|
const cloneBranch = sourcePath ? null : defaultCloneBranchForVersion(getPackageVersion());
|
|
6821
7082
|
const cloneArgs = ["clone"];
|
|
@@ -6856,10 +7117,11 @@ async function serverInstall(flags) {
|
|
|
6856
7117
|
saveServerConfig({
|
|
6857
7118
|
installPath,
|
|
6858
7119
|
installedAt: Date.now(),
|
|
6859
|
-
composeProfile: "core"
|
|
7120
|
+
composeProfile: "core",
|
|
7121
|
+
installMode: "source"
|
|
6860
7122
|
});
|
|
6861
7123
|
if (flags.json === true) {
|
|
6862
|
-
printJson({ command: "install", status: "success", path: installPath });
|
|
7124
|
+
printJson({ command: "install", status: "success", path: installPath, mode: "source" });
|
|
6863
7125
|
} else {
|
|
6864
7126
|
console.log(`
|
|
6865
7127
|
OpenMates installed at ${installPath}`);
|
|
@@ -6871,11 +7133,29 @@ OpenMates installed at ${installPath}`);
|
|
|
6871
7133
|
}
|
|
6872
7134
|
}
|
|
6873
7135
|
async function serverUpdate(flags) {
|
|
6874
|
-
requireGit();
|
|
6875
7136
|
requireDocker();
|
|
6876
7137
|
const installPath = resolveServerPath(flags);
|
|
6877
7138
|
ensureGitWorkDirEnv(installPath);
|
|
6878
7139
|
console.error("Updating OpenMates...");
|
|
7140
|
+
const config = loadConfigForInstallPath(installPath);
|
|
7141
|
+
const withOverrides = config?.composeProfile === "full";
|
|
7142
|
+
const installMode = getInstallMode(installPath, config);
|
|
7143
|
+
if (installMode === "image") {
|
|
7144
|
+
const pullArgs = [...composeArgs(installPath, withOverrides, installMode), "pull"];
|
|
7145
|
+
console.error("Pulling prebuilt images...");
|
|
7146
|
+
let code2 = await runInteractive("docker", pullArgs, installPath);
|
|
7147
|
+
if (code2 !== 0) process.exit(code2);
|
|
7148
|
+
const upArgs2 = [...composeArgs(installPath, withOverrides, installMode), "up", "-d"];
|
|
7149
|
+
code2 = await runInteractive("docker", upArgs2, installPath);
|
|
7150
|
+
if (code2 !== 0) process.exit(code2);
|
|
7151
|
+
if (flags.json === true) {
|
|
7152
|
+
printJson({ command: "update", status: "success", path: installPath, mode: "image" });
|
|
7153
|
+
} else {
|
|
7154
|
+
console.log("Server images pulled and containers restarted.");
|
|
7155
|
+
}
|
|
7156
|
+
return;
|
|
7157
|
+
}
|
|
7158
|
+
requireGit();
|
|
6879
7159
|
if (flags.force === true) {
|
|
6880
7160
|
console.error("Stashing local changes...");
|
|
6881
7161
|
try {
|
|
@@ -6903,13 +7183,11 @@ async function serverUpdate(flags) {
|
|
|
6903
7183
|
} catch {
|
|
6904
7184
|
}
|
|
6905
7185
|
}
|
|
6906
|
-
const
|
|
6907
|
-
const withOverrides = config?.composeProfile === "full";
|
|
6908
|
-
const buildArgs = [...composeArgs(installPath, withOverrides), "build"];
|
|
7186
|
+
const buildArgs = [...composeArgs(installPath, withOverrides, installMode), "build"];
|
|
6909
7187
|
console.error("Rebuilding containers...");
|
|
6910
7188
|
let code = await runInteractive("docker", buildArgs, installPath);
|
|
6911
7189
|
if (code !== 0) process.exit(code);
|
|
6912
|
-
const upArgs = [...composeArgs(installPath, withOverrides), "up", "-d"];
|
|
7190
|
+
const upArgs = [...composeArgs(installPath, withOverrides, installMode), "up", "-d"];
|
|
6913
7191
|
code = await runInteractive("docker", upArgs, installPath);
|
|
6914
7192
|
if (code !== 0) process.exit(code);
|
|
6915
7193
|
if (flags.json === true) {
|
|
@@ -6922,8 +7200,9 @@ async function serverReset(flags) {
|
|
|
6922
7200
|
requireDocker();
|
|
6923
7201
|
const installPath = resolveServerPath(flags);
|
|
6924
7202
|
ensureGitWorkDirEnv(installPath);
|
|
6925
|
-
const config =
|
|
7203
|
+
const config = loadConfigForInstallPath(installPath);
|
|
6926
7204
|
const withOverrides = config?.composeProfile === "full";
|
|
7205
|
+
const installMode = getInstallMode(installPath, config);
|
|
6927
7206
|
const userDataOnly = flags["delete-user-data-only"] === true;
|
|
6928
7207
|
if (userDataOnly) {
|
|
6929
7208
|
console.error("\nWARNING: This will delete all user data (database and cache).");
|
|
@@ -6943,24 +7222,26 @@ async function serverReset(flags) {
|
|
|
6943
7222
|
}
|
|
6944
7223
|
console.error("Resetting server...");
|
|
6945
7224
|
if (userDataOnly) {
|
|
6946
|
-
const downArgs = [...composeArgs(installPath, withOverrides), "down"];
|
|
7225
|
+
const downArgs = [...composeArgs(installPath, withOverrides, installMode), "down"];
|
|
6947
7226
|
let code = await runInteractive("docker", downArgs, installPath);
|
|
6948
7227
|
if (code !== 0) process.exit(code);
|
|
6949
|
-
for (const vol of ["openmates-cache-data", "openmates-cms-database-data"]) {
|
|
7228
|
+
for (const vol of ["openmates-cache-data", "openmates-postgres-data", "openmates-cms-database-data"]) {
|
|
6950
7229
|
try {
|
|
6951
7230
|
exec(`docker volume rm ${vol}`, installPath);
|
|
6952
7231
|
console.error(` Removed volume: ${vol}`);
|
|
6953
7232
|
} catch {
|
|
6954
7233
|
}
|
|
6955
7234
|
}
|
|
6956
|
-
|
|
6957
|
-
|
|
6958
|
-
|
|
6959
|
-
|
|
7235
|
+
if (installMode === "source") {
|
|
7236
|
+
const buildArgs = [...composeArgs(installPath, withOverrides, installMode), "build"];
|
|
7237
|
+
code = await runInteractive("docker", buildArgs, installPath);
|
|
7238
|
+
if (code !== 0) process.exit(code);
|
|
7239
|
+
}
|
|
7240
|
+
const upArgs = [...composeArgs(installPath, withOverrides, installMode), "up", "-d"];
|
|
6960
7241
|
code = await runInteractive("docker", upArgs, installPath);
|
|
6961
7242
|
if (code !== 0) process.exit(code);
|
|
6962
7243
|
} else {
|
|
6963
|
-
const args = [...composeArgs(installPath, withOverrides), "down", "-v"];
|
|
7244
|
+
const args = [...composeArgs(installPath, withOverrides, installMode), "down", "-v"];
|
|
6964
7245
|
const code = await runInteractive("docker", args, installPath);
|
|
6965
7246
|
if (code !== 0) process.exit(code);
|
|
6966
7247
|
}
|
|
@@ -7003,7 +7284,7 @@ async function serverUninstall(flags) {
|
|
|
7003
7284
|
requireDocker();
|
|
7004
7285
|
const installPath = resolveServerPath(flags);
|
|
7005
7286
|
ensureGitWorkDirEnv(installPath);
|
|
7006
|
-
const config =
|
|
7287
|
+
const config = loadConfigForInstallPath(installPath);
|
|
7007
7288
|
const withOverrides = config?.composeProfile === "full";
|
|
7008
7289
|
const keepData = flags["keep-data"] === true;
|
|
7009
7290
|
console.error("\nWARNING: This will completely uninstall OpenMates:");
|
|
@@ -7025,7 +7306,7 @@ async function serverUninstall(flags) {
|
|
|
7025
7306
|
}
|
|
7026
7307
|
}
|
|
7027
7308
|
console.error("Uninstalling OpenMates...");
|
|
7028
|
-
const downArgs = [...composeArgs(installPath, withOverrides), "down", "--rmi", "local"];
|
|
7309
|
+
const downArgs = [...composeArgs(installPath, withOverrides, getInstallMode(installPath, config)), "down", "--rmi", "local"];
|
|
7029
7310
|
if (!keepData) {
|
|
7030
7311
|
downArgs.push("-v");
|
|
7031
7312
|
}
|
|
@@ -7058,13 +7339,13 @@ OpenMates Server Management
|
|
|
7058
7339
|
Usage: openmates server <command> [options]
|
|
7059
7340
|
|
|
7060
7341
|
Commands:
|
|
7061
|
-
install Install OpenMates server (
|
|
7342
|
+
install Install OpenMates server (prebuilt GHCR images by default)
|
|
7062
7343
|
start Start the server
|
|
7063
7344
|
stop Stop the server
|
|
7064
7345
|
restart Restart the server
|
|
7065
7346
|
status Show server status (container health)
|
|
7066
7347
|
logs Display server logs
|
|
7067
|
-
update Update to latest version (git pull + rebuild)
|
|
7348
|
+
update Update to latest version (pull images, or git pull + rebuild for source installs)
|
|
7068
7349
|
make-admin Grant admin privileges to a user
|
|
7069
7350
|
reset Reset server data (requires confirmation)
|
|
7070
7351
|
uninstall Completely remove OpenMates (requires confirmation)
|
|
@@ -7078,7 +7359,9 @@ Command Options:
|
|
|
7078
7359
|
install:
|
|
7079
7360
|
--path <dir> Install directory (default: ~/openmates)
|
|
7080
7361
|
--env-path <file> Copy a pre-existing .env file during install
|
|
7081
|
-
--
|
|
7362
|
+
--image-tag <tag> Prebuilt image tag (default: CLI version tag)
|
|
7363
|
+
--from-source Clone/build from source instead of using prebuilt GHCR images
|
|
7364
|
+
--source-path <dir> Clone from a local checkout instead of GitHub (implies --from-source)
|
|
7082
7365
|
|
|
7083
7366
|
start:
|
|
7084
7367
|
--with-overrides Include admin UIs (Directus CMS, Grafana)
|
|
@@ -9338,8 +9621,44 @@ async function sendMessageStreaming(client, params, redactor) {
|
|
|
9338
9621
|
try {
|
|
9339
9622
|
const session = client.getSession();
|
|
9340
9623
|
const uploadResult = await uploadFile(fe.localPath, session);
|
|
9341
|
-
fe.embed.
|
|
9342
|
-
|
|
9624
|
+
const embedType = fe.embed.type;
|
|
9625
|
+
const audioTranscription = embedType === "audio-recording" ? await transcribeUploadedAudio(
|
|
9626
|
+
uploadResult,
|
|
9627
|
+
fe.displayName,
|
|
9628
|
+
session,
|
|
9629
|
+
{ chatId: params.chatId, requestId: uploadResult.embed_id }
|
|
9630
|
+
) : null;
|
|
9631
|
+
const uploadedContent = embedType === "audio-recording" ? {
|
|
9632
|
+
app_id: "audio",
|
|
9633
|
+
skill_id: "transcribe",
|
|
9634
|
+
type: "audio-recording",
|
|
9635
|
+
status: "finished",
|
|
9636
|
+
filename: fe.displayName,
|
|
9637
|
+
mime_type: uploadResult.content_type,
|
|
9638
|
+
transcript: audioTranscription?.transcript ?? null,
|
|
9639
|
+
transcript_original: audioTranscription?.transcript_original ?? null,
|
|
9640
|
+
transcript_corrected: audioTranscription?.transcript_corrected ?? null,
|
|
9641
|
+
use_corrected: audioTranscription?.use_corrected ?? null,
|
|
9642
|
+
correction_model: audioTranscription?.correction_model ?? null,
|
|
9643
|
+
model: audioTranscription?.model ?? null,
|
|
9644
|
+
s3_base_url: uploadResult.s3_base_url,
|
|
9645
|
+
files: uploadResult.files,
|
|
9646
|
+
aes_key: uploadResult.aes_key,
|
|
9647
|
+
aes_nonce: uploadResult.aes_nonce,
|
|
9648
|
+
vault_wrapped_aes_key: uploadResult.vault_wrapped_aes_key
|
|
9649
|
+
} : embedType === "pdf" ? {
|
|
9650
|
+
type: "pdf",
|
|
9651
|
+
status: "processing",
|
|
9652
|
+
filename: fe.displayName,
|
|
9653
|
+
page_count: uploadResult.page_count ?? null,
|
|
9654
|
+
content_hash: uploadResult.content_hash,
|
|
9655
|
+
s3_base_url: uploadResult.s3_base_url,
|
|
9656
|
+
files: uploadResult.files,
|
|
9657
|
+
aes_key: uploadResult.aes_key,
|
|
9658
|
+
aes_nonce: uploadResult.aes_nonce,
|
|
9659
|
+
vault_wrapped_aes_key: uploadResult.vault_wrapped_aes_key
|
|
9660
|
+
} : {
|
|
9661
|
+
type: "image",
|
|
9343
9662
|
app_id: "images",
|
|
9344
9663
|
skill_id: "upload",
|
|
9345
9664
|
status: "finished",
|
|
@@ -9351,10 +9670,15 @@ async function sendMessageStreaming(client, params, redactor) {
|
|
|
9351
9670
|
aes_nonce: uploadResult.aes_nonce,
|
|
9352
9671
|
vault_wrapped_aes_key: uploadResult.vault_wrapped_aes_key,
|
|
9353
9672
|
ai_detection: uploadResult.ai_detection
|
|
9354
|
-
}
|
|
9355
|
-
fe.embed.
|
|
9673
|
+
};
|
|
9674
|
+
fe.embed.content = toonEncodeContent(uploadedContent);
|
|
9675
|
+
fe.embed.status = embedType === "pdf" ? "processing" : "finished";
|
|
9356
9676
|
fe.embed.contentHash = uploadResult.content_hash;
|
|
9357
9677
|
fe.embed.embedId = uploadResult.embed_id;
|
|
9678
|
+
fe.referenceBlock = createEmbedReferenceBlock(
|
|
9679
|
+
embedType,
|
|
9680
|
+
uploadResult.embed_id
|
|
9681
|
+
);
|
|
9358
9682
|
if (!params.json) {
|
|
9359
9683
|
process.stderr.write(
|
|
9360
9684
|
`\x1B[32m \u2713\x1B[0m \x1B[2m${fe.displayName} uploaded\x1B[0m
|
package/dist/cli.js
CHANGED
package/dist/index.js
CHANGED