openmates 0.16.0-alpha.0 → 0.16.0-alpha.10
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.
|
@@ -21607,6 +21607,13 @@ var OpenMatesPlans = class {
|
|
|
21607
21607
|
return response.entries ?? [];
|
|
21608
21608
|
}
|
|
21609
21609
|
async getRawPlan(planId) {
|
|
21610
|
+
try {
|
|
21611
|
+
const response = await this.client.get(`/v1/user-plans/${encodeURIComponent(planId)}`);
|
|
21612
|
+
if (!response.plan) throw new OpenMatesApiError(500, { detail: "User plan response missing plan" });
|
|
21613
|
+
return response.plan;
|
|
21614
|
+
} catch (error) {
|
|
21615
|
+
if (!(error instanceof OpenMatesApiError) || error.status !== 404) throw error;
|
|
21616
|
+
}
|
|
21610
21617
|
const plans = await this.listRaw({ activeOnly: false });
|
|
21611
21618
|
const plan = plans.find((candidate) => candidate.plan_id === planId || candidate.plan_id?.startsWith(planId));
|
|
21612
21619
|
if (!plan) throw new OpenMatesApiError(404, { detail: "Plan not found" });
|
|
@@ -24640,6 +24647,7 @@ var CORE_WORKER_SERVICES = [
|
|
|
24640
24647
|
"task-worker",
|
|
24641
24648
|
"user-init-worker",
|
|
24642
24649
|
"core-worker",
|
|
24650
|
+
"reminder-worker",
|
|
24643
24651
|
"task-scheduler",
|
|
24644
24652
|
"app-ai-worker",
|
|
24645
24653
|
"app-images-worker",
|
|
@@ -24652,6 +24660,7 @@ var CORE_WORKER_SERVICES = [
|
|
|
24652
24660
|
];
|
|
24653
24661
|
var OPENMATESCLOUD_OVERLAY_DIR = "OpenMatesCloud";
|
|
24654
24662
|
var OPENMATESCLOUD_COMPOSE_FILE = "docker-compose.openmatescloud.yml";
|
|
24663
|
+
var OFFICIAL_CLOUD_NO_WEBAPP_COMPOSE_FILE = "backend/core/docker-compose.no-webapp.yml";
|
|
24655
24664
|
var SOURCE_COMPOSE_FILES = {
|
|
24656
24665
|
core: "backend/core/docker-compose.yml",
|
|
24657
24666
|
upload: "backend/upload/docker-compose.yml",
|
|
@@ -24724,6 +24733,7 @@ var INTEGRATION_SECRET_PREFIXES = [
|
|
|
24724
24733
|
"SECRET__REVOLUT_BUSINESS__",
|
|
24725
24734
|
"SECRET__INVOICE_"
|
|
24726
24735
|
];
|
|
24736
|
+
var CELERY_PROBE_CHECK_TIMEOUT_SECONDS = 15;
|
|
24727
24737
|
var RUNTIME_CHECKS = {
|
|
24728
24738
|
core: [
|
|
24729
24739
|
{ id: "compose.required_services", required: true, timeoutSeconds: 15 },
|
|
@@ -24731,8 +24741,8 @@ var RUNTIME_CHECKS = {
|
|
|
24731
24741
|
{ id: "core.database", required: true, timeoutSeconds: 10 },
|
|
24732
24742
|
{ id: "core.cache", required: true, timeoutSeconds: 10 },
|
|
24733
24743
|
{ id: "core.vault", required: true, timeoutSeconds: 10 },
|
|
24734
|
-
{ id: "core.worker_queue", required: true, timeoutSeconds:
|
|
24735
|
-
{ id: "core.scheduler_freshness", required: true, timeoutSeconds:
|
|
24744
|
+
{ id: "core.worker_queue", required: true, timeoutSeconds: CELERY_PROBE_CHECK_TIMEOUT_SECONDS },
|
|
24745
|
+
{ id: "core.scheduler_freshness", required: true, timeoutSeconds: CELERY_PROBE_CHECK_TIMEOUT_SECONDS },
|
|
24736
24746
|
{ id: "core.chat_plumbing", required: true, timeoutSeconds: 20 }
|
|
24737
24747
|
],
|
|
24738
24748
|
upload: [
|
|
@@ -24867,7 +24877,7 @@ function planOpenMatesCloudOverlay(input) {
|
|
|
24867
24877
|
deploymentMode,
|
|
24868
24878
|
enabled: true,
|
|
24869
24879
|
overlayPath,
|
|
24870
|
-
composeFiles: [overlayComposeFile],
|
|
24880
|
+
composeFiles: [overlayComposeFile, OFFICIAL_CLOUD_NO_WEBAPP_COMPOSE_FILE],
|
|
24871
24881
|
env: {
|
|
24872
24882
|
OPENMATES_CLOUD_OVERLAY_ENABLED: "true",
|
|
24873
24883
|
OPENMATES_CLOUD_OVERLAY_PATH: overlayPath
|
|
@@ -24937,6 +24947,7 @@ function appendSelectedServices(args, selectedServices, filterRequested) {
|
|
|
24937
24947
|
function shouldCheckWebHealth(input) {
|
|
24938
24948
|
const role = parseServerRole(input.role);
|
|
24939
24949
|
if (role !== "core") return false;
|
|
24950
|
+
if (input.deploymentMode === "official_cloud") return false;
|
|
24940
24951
|
return input.filterRequested !== true || (input.selectedServices ?? []).includes("webapp");
|
|
24941
24952
|
}
|
|
24942
24953
|
function planUpdate(input) {
|
|
@@ -25198,6 +25209,9 @@ function planRuntimeMonitoringServices(input) {
|
|
|
25198
25209
|
].join("\n")
|
|
25199
25210
|
};
|
|
25200
25211
|
}
|
|
25212
|
+
function shouldAutoInstallRuntimeMonitoringServices(env) {
|
|
25213
|
+
return env.OPENMATES_SKIP_RUNTIME_MONITORING !== "1";
|
|
25214
|
+
}
|
|
25201
25215
|
|
|
25202
25216
|
// src/serverHealth.ts
|
|
25203
25217
|
import dnsModule, { promises as dns } from "dns";
|
|
@@ -25472,6 +25486,7 @@ var ROLE_TEMPLATE_FILES = {
|
|
|
25472
25486
|
upload: join6("upload", "docker-compose.yml"),
|
|
25473
25487
|
preview: join6("preview", "docker-compose.preview.yml")
|
|
25474
25488
|
};
|
|
25489
|
+
var CORE_NO_WEBAPP_TEMPLATE_FILE = join6("core", "docker-compose.no-webapp.yml");
|
|
25475
25490
|
var CORE_PROMTAIL_CONFIG_FILE = join6("backend", "core", "monitoring", "promtail", "promtail-config.yaml");
|
|
25476
25491
|
var COMPOSE_OVERRIDE2 = join6("backend", "core", "docker-compose.override.yml");
|
|
25477
25492
|
var DEFAULT_INSTALL_PATH = join6(homedir6(), "openmates");
|
|
@@ -25723,6 +25738,12 @@ function getServerDeploymentMode(flags, config) {
|
|
|
25723
25738
|
if (typeof flags["deployment-mode"] === "string") return normalizeServerDeploymentMode(flags["deployment-mode"]);
|
|
25724
25739
|
return normalizeServerDeploymentMode(config?.deploymentMode);
|
|
25725
25740
|
}
|
|
25741
|
+
function getInstallDeploymentMode(installPath, config) {
|
|
25742
|
+
const env = readEnvMap(installPath);
|
|
25743
|
+
if (env.OPENMATES_CLOUD_OVERLAY_ENABLED === "true") return "official_cloud";
|
|
25744
|
+
if (env.OPENMATES_CLOUD_OVERLAY_ENABLED === "false") return "self_host";
|
|
25745
|
+
return normalizeServerDeploymentMode(config?.deploymentMode);
|
|
25746
|
+
}
|
|
25726
25747
|
function getOpenMatesCloudOverlayPath(flags, config) {
|
|
25727
25748
|
const explicit = flags["openmatescloud-path"] ?? flags["openmates-cloud-path"];
|
|
25728
25749
|
if (explicit === true) throw new Error("Provide an OpenMatesCloud path: --openmatescloud-path <dir>.");
|
|
@@ -25801,9 +25822,10 @@ function featureKind(featureId) {
|
|
|
25801
25822
|
return featureId.split(":", 1)[0] || "unknown";
|
|
25802
25823
|
}
|
|
25803
25824
|
function composeArgs(installPath, withOverrides, installMode = getInstallMode(installPath), role = "core") {
|
|
25804
|
-
const env = readEnvMap(installPath);
|
|
25805
25825
|
const config = loadConfigForInstallPath(installPath);
|
|
25806
|
-
const deploymentMode =
|
|
25826
|
+
const deploymentMode = getInstallDeploymentMode(installPath, config);
|
|
25827
|
+
ensureOfficialCloudNoWebappComposeFile(installPath, deploymentMode, role);
|
|
25828
|
+
const env = readEnvMap(installPath);
|
|
25807
25829
|
const overlayPath = env.OPENMATES_CLOUD_OVERLAY_PATH || config?.openMatesCloudOverlayPath || void 0;
|
|
25808
25830
|
const resolvedOverlayPath = overlayPath ?? defaultOpenMatesCloudOverlayPath(installPath);
|
|
25809
25831
|
const overlayComposeFile = defaultOpenMatesCloudComposeFile(resolvedOverlayPath);
|
|
@@ -25947,9 +25969,34 @@ async function fetchText(url) {
|
|
|
25947
25969
|
function packagedTemplatePath(role) {
|
|
25948
25970
|
return join6(dirname5(new URL(import.meta.url).pathname), "..", "templates", ROLE_TEMPLATE_FILES[role]);
|
|
25949
25971
|
}
|
|
25972
|
+
function packagedNoWebappTemplatePath() {
|
|
25973
|
+
return join6(dirname5(new URL(import.meta.url).pathname), "..", "templates", CORE_NO_WEBAPP_TEMPLATE_FILE);
|
|
25974
|
+
}
|
|
25950
25975
|
function packagedCaddyTemplatePath(role) {
|
|
25951
25976
|
return join6(dirname5(new URL(import.meta.url).pathname), "..", "templates", "caddy", role, "Caddyfile");
|
|
25952
25977
|
}
|
|
25978
|
+
function readOfficialCloudNoWebappComposeTemplate() {
|
|
25979
|
+
const packaged = packagedNoWebappTemplatePath();
|
|
25980
|
+
if (existsSync8(packaged)) return readFileSync6(packaged, "utf-8");
|
|
25981
|
+
return [
|
|
25982
|
+
"# backend/core/docker-compose.no-webapp.yml",
|
|
25983
|
+
"#",
|
|
25984
|
+
"# Keeps official OpenMatesCloud core runtimes backend-only while regular",
|
|
25985
|
+
"# self-host installs continue to start the webapp from the base compose file.",
|
|
25986
|
+
"",
|
|
25987
|
+
"services:",
|
|
25988
|
+
" webapp:",
|
|
25989
|
+
' profiles: ["webapp"]',
|
|
25990
|
+
""
|
|
25991
|
+
].join("\n");
|
|
25992
|
+
}
|
|
25993
|
+
function ensureOfficialCloudNoWebappComposeFile(installPath, deploymentMode, role) {
|
|
25994
|
+
if (deploymentMode !== "official_cloud" || role !== "core") return;
|
|
25995
|
+
const filePath = join6(installPath, OFFICIAL_CLOUD_NO_WEBAPP_COMPOSE_FILE);
|
|
25996
|
+
if (existsSync8(filePath)) return;
|
|
25997
|
+
mkdirSync5(dirname5(filePath), { recursive: true });
|
|
25998
|
+
writeFileSync4(filePath, readOfficialCloudNoWebappComposeTemplate());
|
|
25999
|
+
}
|
|
25953
26000
|
function fileHash(path2) {
|
|
25954
26001
|
if (!existsSync8(path2)) return null;
|
|
25955
26002
|
return createHash12("sha256").update(readFileSync6(path2)).digest("hex");
|
|
@@ -25973,6 +26020,9 @@ async function writeImageModeRuntimeFiles(installPath, imageTag, role) {
|
|
|
25973
26020
|
mkdirSync5(vaultConfigDir, { recursive: true });
|
|
25974
26021
|
mkdirSync5(join6(installPath, "config", "providers"), { recursive: true });
|
|
25975
26022
|
writeFileSync4(join6(installPath, ROLE_IMAGE_COMPOSE_FILES[role]), await loadSelfHostComposeTemplate(templateRefForImageTag(imageTag, getPackageVersion()), role));
|
|
26023
|
+
if (role === "core") {
|
|
26024
|
+
writeFileSync4(join6(installPath, OFFICIAL_CLOUD_NO_WEBAPP_COMPOSE_FILE), readOfficialCloudNoWebappComposeTemplate());
|
|
26025
|
+
}
|
|
25976
26026
|
if (role === "core") {
|
|
25977
26027
|
const promtailConfigPath = join6(installPath, CORE_PROMTAIL_CONFIG_FILE);
|
|
25978
26028
|
mkdirSync5(dirname5(promtailConfigPath), { recursive: true });
|
|
@@ -26708,6 +26758,7 @@ async function serverStart(flags) {
|
|
|
26708
26758
|
const config = loadConfigForInstallPath(installPath);
|
|
26709
26759
|
const role = getServerRole(flags, config);
|
|
26710
26760
|
const installMode = getInstallMode(installPath, config);
|
|
26761
|
+
const deploymentMode = getInstallDeploymentMode(installPath, config);
|
|
26711
26762
|
const pullArgs = [...composeArgs(installPath, withOverrides, installMode, role), "pull"];
|
|
26712
26763
|
const args = [...composeArgs(installPath, withOverrides, installMode, role), "up", "-d"];
|
|
26713
26764
|
if (hasServiceFilter(flags)) {
|
|
@@ -26730,8 +26781,12 @@ async function serverStart(flags) {
|
|
|
26730
26781
|
printJson({ command: "start", status: "success", path: installPath });
|
|
26731
26782
|
} else {
|
|
26732
26783
|
console.log("\nServer started.");
|
|
26733
|
-
console.log("Web app: http://localhost:5173");
|
|
26734
26784
|
console.log("API: http://localhost:8000");
|
|
26785
|
+
if (deploymentMode === "official_cloud") {
|
|
26786
|
+
console.log("Web app: deployed separately for official cloud");
|
|
26787
|
+
} else {
|
|
26788
|
+
console.log("Web app: http://localhost:5173");
|
|
26789
|
+
}
|
|
26735
26790
|
if (withOverrides) {
|
|
26736
26791
|
console.log("Directus CMS: http://localhost:8055");
|
|
26737
26792
|
console.log("Grafana: http://localhost:3000");
|
|
@@ -26880,7 +26935,7 @@ async function serverInstall(flags) {
|
|
|
26880
26935
|
...cliUrls2
|
|
26881
26936
|
});
|
|
26882
26937
|
try {
|
|
26883
|
-
|
|
26938
|
+
autoInstallRuntimeMonitoringServices(installPath, role);
|
|
26884
26939
|
} catch (error) {
|
|
26885
26940
|
throw new Error(`Server files were installed but runtime monitoring service installation failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
26886
26941
|
}
|
|
@@ -26964,7 +27019,7 @@ CLI default API: ${cliUrls2.apiUrl}`);
|
|
|
26964
27019
|
...cliUrls
|
|
26965
27020
|
});
|
|
26966
27021
|
try {
|
|
26967
|
-
|
|
27022
|
+
autoInstallRuntimeMonitoringServices(installPath, role);
|
|
26968
27023
|
} catch (error) {
|
|
26969
27024
|
throw new Error(`Server files were installed but runtime monitoring service installation failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
26970
27025
|
}
|
|
@@ -27111,6 +27166,14 @@ function installRuntimeMonitoringServices(installPath, role) {
|
|
|
27111
27166
|
execSync(`systemctl enable --now ${timers.map(shellQuote).join(" ")}`, { stdio: "pipe" });
|
|
27112
27167
|
for (const timer of timers) execFileSync3("systemctl", ["is-active", "--quiet", timer], { stdio: "pipe" });
|
|
27113
27168
|
}
|
|
27169
|
+
function autoInstallRuntimeMonitoringServices(installPath, role) {
|
|
27170
|
+
if (!shouldAutoInstallRuntimeMonitoringServices(process.env)) {
|
|
27171
|
+
console.error("Skipping runtime monitoring service installation because OPENMATES_SKIP_RUNTIME_MONITORING=1.");
|
|
27172
|
+
return "skipped";
|
|
27173
|
+
}
|
|
27174
|
+
installRuntimeMonitoringServices(installPath, role);
|
|
27175
|
+
return "installed";
|
|
27176
|
+
}
|
|
27114
27177
|
async function serverUpdate(rest, flags) {
|
|
27115
27178
|
if (rest[0] === "status") {
|
|
27116
27179
|
const installPath2 = resolveServerPath(flags);
|
|
@@ -27149,6 +27212,7 @@ async function serverUpdate(rest, flags) {
|
|
|
27149
27212
|
const role = getServerRole(flags, config);
|
|
27150
27213
|
const withOverrides = config?.composeProfile === "full";
|
|
27151
27214
|
const installMode = getInstallMode(installPath, config);
|
|
27215
|
+
const deploymentMode = getInstallDeploymentMode(installPath, config);
|
|
27152
27216
|
const filterRequested = hasServiceFilter(flags);
|
|
27153
27217
|
const selectedServices = filterRequested ? selectedComposeServices(role, flags) : [];
|
|
27154
27218
|
const missingEnvKeys = missingRequiredEnvKeys(installPath, role);
|
|
@@ -27261,7 +27325,7 @@ async function serverUpdate(rest, flags) {
|
|
|
27261
27325
|
try {
|
|
27262
27326
|
writeUpdateStatus(installPath, role, { status: "in_progress", targetImageTag: target.tag, sourceLinks, providerKeyReminders: secretPreflight.emptySecretEnvKeys, step: "health-check" });
|
|
27263
27327
|
await waitForServerHealth(installPath, role, {
|
|
27264
|
-
checkWebApp: shouldCheckWebHealth({ role, selectedServices, filterRequested })
|
|
27328
|
+
checkWebApp: shouldCheckWebHealth({ role, deploymentMode, selectedServices, filterRequested })
|
|
27265
27329
|
});
|
|
27266
27330
|
const runtimeOutput = runRuntimeVerification(installPath, role, config);
|
|
27267
27331
|
await persistRuntimeResult(installPath, role, runtimeOutput);
|
|
@@ -27269,7 +27333,7 @@ async function serverUpdate(rest, flags) {
|
|
|
27269
27333
|
const notificationDelivery = await dispatchRuntimeEvent(installPath, role, "post_update_failed", runtimeOutput.checks, (/* @__PURE__ */ new Date()).toISOString());
|
|
27270
27334
|
let monitoringProvision = "installed";
|
|
27271
27335
|
try {
|
|
27272
|
-
|
|
27336
|
+
monitoringProvision = autoInstallRuntimeMonitoringServices(installPath, role);
|
|
27273
27337
|
} catch {
|
|
27274
27338
|
monitoringProvision = "failed";
|
|
27275
27339
|
}
|
|
@@ -27295,7 +27359,7 @@ async function serverUpdate(rest, flags) {
|
|
|
27295
27359
|
saveServerConfig({ ...config, imageTag: target.tag, imageChannel: target.channel });
|
|
27296
27360
|
}
|
|
27297
27361
|
try {
|
|
27298
|
-
|
|
27362
|
+
autoInstallRuntimeMonitoringServices(installPath, role);
|
|
27299
27363
|
} catch (error) {
|
|
27300
27364
|
const restoreCommand = safetyPlan.backupName ? `openmates server restore --role ${role} --file ${join6(roleBackupDir(installPath, role), safetyPlan.backupName)}` : null;
|
|
27301
27365
|
writeUpdateStatus(installPath, role, {
|
|
@@ -27331,14 +27395,14 @@ async function serverUpdate(rest, flags) {
|
|
|
27331
27395
|
path: installPath,
|
|
27332
27396
|
mode: "source",
|
|
27333
27397
|
selectedServices: filterRequested ? selectedServices : "all",
|
|
27334
|
-
checkWebApp: shouldCheckWebHealth({ role, selectedServices, filterRequested }),
|
|
27398
|
+
checkWebApp: shouldCheckWebHealth({ role, deploymentMode, selectedServices, filterRequested }),
|
|
27335
27399
|
dryRun: true
|
|
27336
27400
|
});
|
|
27337
27401
|
} else {
|
|
27338
27402
|
console.log("Update plan:");
|
|
27339
27403
|
console.log(" Mode: source");
|
|
27340
27404
|
console.log(` Services: ${filterRequested ? selectedServices.join(", ") : "all"}`);
|
|
27341
|
-
console.log(` Web health: ${shouldCheckWebHealth({ role, selectedServices, filterRequested }) ? "enabled" : "skipped"}`);
|
|
27405
|
+
console.log(` Web health: ${shouldCheckWebHealth({ role, deploymentMode, selectedServices, filterRequested }) ? "enabled" : "skipped"}`);
|
|
27342
27406
|
console.log(" Commands: git pull --ff-only, docker compose build, docker compose up -d, health checks");
|
|
27343
27407
|
}
|
|
27344
27408
|
return;
|
|
@@ -27386,7 +27450,7 @@ async function serverUpdate(rest, flags) {
|
|
|
27386
27450
|
);
|
|
27387
27451
|
code = await runInteractive("docker", upArgs, installPath);
|
|
27388
27452
|
if (code !== 0) process.exit(code);
|
|
27389
|
-
const checkWebApp = shouldCheckWebHealth({ role, selectedServices, filterRequested });
|
|
27453
|
+
const checkWebApp = shouldCheckWebHealth({ role, deploymentMode, selectedServices, filterRequested });
|
|
27390
27454
|
console.error(checkWebApp ? "Waiting for API and web health checks..." : "Waiting for API health checks...");
|
|
27391
27455
|
let successfulRuntimeOutput = null;
|
|
27392
27456
|
try {
|
|
@@ -27397,7 +27461,7 @@ async function serverUpdate(rest, flags) {
|
|
|
27397
27461
|
const notificationDelivery = await dispatchRuntimeEvent(installPath, role, "post_update_failed", runtimeOutput.checks, (/* @__PURE__ */ new Date()).toISOString());
|
|
27398
27462
|
let monitoringProvision = "installed";
|
|
27399
27463
|
try {
|
|
27400
|
-
|
|
27464
|
+
monitoringProvision = autoInstallRuntimeMonitoringServices(installPath, role);
|
|
27401
27465
|
} catch {
|
|
27402
27466
|
monitoringProvision = "failed";
|
|
27403
27467
|
}
|
|
@@ -27419,7 +27483,7 @@ async function serverUpdate(rest, flags) {
|
|
|
27419
27483
|
throw error;
|
|
27420
27484
|
}
|
|
27421
27485
|
try {
|
|
27422
|
-
|
|
27486
|
+
autoInstallRuntimeMonitoringServices(installPath, role);
|
|
27423
27487
|
} catch (error) {
|
|
27424
27488
|
writeUpdateStatus(installPath, role, { status: "degraded", step: "monitoring-service", restoreStatus: "restore_unavailable", restoreCommand: null });
|
|
27425
27489
|
throw new Error(`Runtime checks passed but monitoring service installation failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
@@ -45157,6 +45221,172 @@ notebook:
|
|
|
45157
45221
|
}
|
|
45158
45222
|
};
|
|
45159
45223
|
|
|
45224
|
+
// ../ui/src/demo_chats/data/example_chats/audio-generate-product-success-chime.ts
|
|
45225
|
+
var audioGenerateProductSuccessChimeChat = {
|
|
45226
|
+
chat_id: "example-audio-generate-product-success-chime",
|
|
45227
|
+
slug: "audio-generate-product-success-chime",
|
|
45228
|
+
title: "example_chats.audio_generate_product_success_chime.title",
|
|
45229
|
+
summary: "example_chats.audio_generate_product_success_chime.summary",
|
|
45230
|
+
icon: "volume2",
|
|
45231
|
+
category: "design",
|
|
45232
|
+
keywords: ["audio generation", "sound effects", "ElevenLabs", "product sound", "OpenMates apps"],
|
|
45233
|
+
follow_up_suggestions: [],
|
|
45234
|
+
messages: [
|
|
45235
|
+
{
|
|
45236
|
+
id: "0fe80324-42f5-4b87-9e11-0b0d8f36c9d5",
|
|
45237
|
+
role: "user",
|
|
45238
|
+
content: "example_chats.audio_generate_product_success_chime.message_1",
|
|
45239
|
+
created_at: 1786382134
|
|
45240
|
+
},
|
|
45241
|
+
{
|
|
45242
|
+
id: "87bb2a45-d06b-4afa-8a4d-d2f4173647b8",
|
|
45243
|
+
role: "assistant",
|
|
45244
|
+
content: "example_chats.audio_generate_product_success_chime.message_2",
|
|
45245
|
+
created_at: 1786382154,
|
|
45246
|
+
user_message_id: "0fe80324-42f5-4b87-9e11-0b0d8f36c9d5",
|
|
45247
|
+
response_credits: 31,
|
|
45248
|
+
category: "general_knowledge",
|
|
45249
|
+
model_name: "Gemini 3.5 Flash-Lite"
|
|
45250
|
+
}
|
|
45251
|
+
],
|
|
45252
|
+
embeds: [
|
|
45253
|
+
{
|
|
45254
|
+
embed_id: "8d96310e-a05a-41e8-a687-08ce2ce1ce9a",
|
|
45255
|
+
type: "app_skill_use",
|
|
45256
|
+
content: 'app_id: audio\nskill_id: generate\ntype: audio\nstatus: finished\nprompt: "Create a short, friendly success chime for an OpenMates workflow finishing"\ngeneration_type: sound_effect\nprovider: ElevenLabs\nmodel: eleven_text_to_sound_v2\nmime_type: audio/mpeg\nduration_seconds: 0.679\nbyte_length: 3531\npreviewAudioUrl: /store-examples/audio-generate-product-success-chime.mp3\nfiles:\n original:\n size_bytes: 3531\n format: mp3\n mime_type: audio/mpeg\n duration_seconds: 0.679\ngenerated_at: "2026-08-11T02:30:00.000000+00:00"\nwatermarking: Static public fixture',
|
|
45257
|
+
parent_embed_id: null,
|
|
45258
|
+
embed_ids: null
|
|
45259
|
+
}
|
|
45260
|
+
],
|
|
45261
|
+
usage_entries: [
|
|
45262
|
+
{
|
|
45263
|
+
id: "example-audio-generate-product-success-chime-usage-1",
|
|
45264
|
+
type: "skill_execution",
|
|
45265
|
+
source: "chat",
|
|
45266
|
+
app_id: "ai",
|
|
45267
|
+
skill_id: "ask",
|
|
45268
|
+
model_used: "google/gemini-3.5-flash-lite",
|
|
45269
|
+
credits: 17,
|
|
45270
|
+
input_tokens: 18477,
|
|
45271
|
+
output_tokens: 107,
|
|
45272
|
+
user_input_tokens: 185,
|
|
45273
|
+
system_prompt_tokens: 8516,
|
|
45274
|
+
server_provider: "Google AI Studio",
|
|
45275
|
+
server_region: "US",
|
|
45276
|
+
chat_id: "example-audio-generate-product-success-chime",
|
|
45277
|
+
message_id: "0fe80324-42f5-4b87-9e11-0b0d8f36c9d5",
|
|
45278
|
+
created_at: 1786382147,
|
|
45279
|
+
updated_at: 1786382147,
|
|
45280
|
+
tool_inference_iterations: 1
|
|
45281
|
+
},
|
|
45282
|
+
{
|
|
45283
|
+
id: "example-audio-generate-product-success-chime-usage-2",
|
|
45284
|
+
type: "skill_execution",
|
|
45285
|
+
source: "chat",
|
|
45286
|
+
app_id: "audio",
|
|
45287
|
+
skill_id: "generate",
|
|
45288
|
+
model_used: "elevenlabs/eleven_text_to_sound_v2",
|
|
45289
|
+
credits: 14,
|
|
45290
|
+
server_provider: "ElevenLabs",
|
|
45291
|
+
server_region: "US",
|
|
45292
|
+
chat_id: "example-audio-generate-product-success-chime",
|
|
45293
|
+
message_id: "0fe80324-42f5-4b87-9e11-0b0d8f36c9d5",
|
|
45294
|
+
created_at: 1786382144,
|
|
45295
|
+
updated_at: 1786382144,
|
|
45296
|
+
tool_inference_iterations: 0,
|
|
45297
|
+
code_run_duration_seconds: 0.679
|
|
45298
|
+
}
|
|
45299
|
+
],
|
|
45300
|
+
metadata: {
|
|
45301
|
+
featured: true,
|
|
45302
|
+
order: 123,
|
|
45303
|
+
app_skill_examples: ["audio.generate"]
|
|
45304
|
+
}
|
|
45305
|
+
};
|
|
45306
|
+
|
|
45307
|
+
// ../ui/src/demo_chats/data/example_chats/audio-speak-friendly-welcome-message.ts
|
|
45308
|
+
var audioSpeakFriendlyWelcomeMessageChat = {
|
|
45309
|
+
chat_id: "example-audio-speak-friendly-welcome-message",
|
|
45310
|
+
slug: "audio-speak-friendly-welcome-message",
|
|
45311
|
+
title: "example_chats.audio_speak_friendly_welcome_message.title",
|
|
45312
|
+
summary: "example_chats.audio_speak_friendly_welcome_message.summary",
|
|
45313
|
+
icon: "volume2",
|
|
45314
|
+
category: "design",
|
|
45315
|
+
keywords: ["text to speech", "ElevenLabs", "speech generation", "voice narration", "OpenMates apps"],
|
|
45316
|
+
follow_up_suggestions: [],
|
|
45317
|
+
messages: [
|
|
45318
|
+
{
|
|
45319
|
+
id: "b39cb42f-ec3e-45ec-9339-801b54c7cb03",
|
|
45320
|
+
role: "user",
|
|
45321
|
+
content: "example_chats.audio_speak_friendly_welcome_message.message_1",
|
|
45322
|
+
created_at: 1786382241
|
|
45323
|
+
},
|
|
45324
|
+
{
|
|
45325
|
+
id: "892c94f0-2c44-4d72-9c92-f27db186a103",
|
|
45326
|
+
role: "assistant",
|
|
45327
|
+
content: "example_chats.audio_speak_friendly_welcome_message.message_2",
|
|
45328
|
+
created_at: 1786382255,
|
|
45329
|
+
user_message_id: "b39cb42f-ec3e-45ec-9339-801b54c7cb03",
|
|
45330
|
+
response_credits: 28,
|
|
45331
|
+
category: "onboarding_support",
|
|
45332
|
+
model_name: "Gemini 3.5 Flash-Lite"
|
|
45333
|
+
}
|
|
45334
|
+
],
|
|
45335
|
+
embeds: [
|
|
45336
|
+
{
|
|
45337
|
+
embed_id: "463ace0f-02f9-43c2-94ee-cf385162bb75",
|
|
45338
|
+
type: "app_skill_use",
|
|
45339
|
+
content: 'app_id: audio\nskill_id: speak\ntype: audio\nstatus: finished\nprompt: "Say this as a warm, natural welcome message: Welcome back to OpenMates. Your workspace is ready whenever you are."\ntext_preview: "Welcome back to OpenMates. Your workspace is ready whenever you are."\ntext: "Welcome back to OpenMates. Your workspace is ready whenever you are."\ngeneration_type: speech\nvoice: warm_neutral\nprovider: ElevenLabs\nmodel: eleven_flash_v2_5\nmime_type: audio/mpeg\nduration_seconds: 4.968\nbyte_length: 28413\npreviewAudioUrl: /store-examples/audio-speak-friendly-welcome-message.mp3\nfiles:\n original:\n size_bytes: 28413\n format: mp3\n mime_type: audio/mpeg\n duration_seconds: 4.968\ngenerated_at: "2026-08-11T02:30:00.000000+00:00"\nwatermarking: Static public fixture',
|
|
45340
|
+
parent_embed_id: null,
|
|
45341
|
+
embed_ids: null
|
|
45342
|
+
}
|
|
45343
|
+
],
|
|
45344
|
+
usage_entries: [
|
|
45345
|
+
{
|
|
45346
|
+
id: "example-audio-speak-friendly-welcome-message-usage-1",
|
|
45347
|
+
type: "skill_execution",
|
|
45348
|
+
source: "chat",
|
|
45349
|
+
app_id: "ai",
|
|
45350
|
+
skill_id: "ask",
|
|
45351
|
+
model_used: "google/gemini-3.5-flash-lite",
|
|
45352
|
+
credits: 18,
|
|
45353
|
+
input_tokens: 19599,
|
|
45354
|
+
output_tokens: 69,
|
|
45355
|
+
user_input_tokens: 181,
|
|
45356
|
+
system_prompt_tokens: 9066,
|
|
45357
|
+
server_provider: "Google AI Studio",
|
|
45358
|
+
server_region: "US",
|
|
45359
|
+
chat_id: "example-audio-speak-friendly-welcome-message",
|
|
45360
|
+
message_id: "b39cb42f-ec3e-45ec-9339-801b54c7cb03",
|
|
45361
|
+
created_at: 1786382249,
|
|
45362
|
+
updated_at: 1786382249,
|
|
45363
|
+
tool_inference_iterations: 1
|
|
45364
|
+
},
|
|
45365
|
+
{
|
|
45366
|
+
id: "example-audio-speak-friendly-welcome-message-usage-2",
|
|
45367
|
+
type: "skill_execution",
|
|
45368
|
+
source: "chat",
|
|
45369
|
+
app_id: "audio",
|
|
45370
|
+
skill_id: "speak",
|
|
45371
|
+
model_used: "elevenlabs/eleven_flash_v2_5",
|
|
45372
|
+
credits: 10,
|
|
45373
|
+
server_provider: "ElevenLabs",
|
|
45374
|
+
server_region: "US",
|
|
45375
|
+
chat_id: "example-audio-speak-friendly-welcome-message",
|
|
45376
|
+
message_id: "b39cb42f-ec3e-45ec-9339-801b54c7cb03",
|
|
45377
|
+
created_at: 1786382246,
|
|
45378
|
+
updated_at: 1786382246,
|
|
45379
|
+
tool_inference_iterations: 0,
|
|
45380
|
+
code_run_duration_seconds: 4.968
|
|
45381
|
+
}
|
|
45382
|
+
],
|
|
45383
|
+
metadata: {
|
|
45384
|
+
featured: true,
|
|
45385
|
+
order: 124,
|
|
45386
|
+
app_skill_examples: ["audio.speak"]
|
|
45387
|
+
}
|
|
45388
|
+
};
|
|
45389
|
+
|
|
45160
45390
|
// ../ui/src/demo_chats/exampleChatData.ts
|
|
45161
45391
|
var ALL_EXAMPLE_CHATS = [
|
|
45162
45392
|
giganticAirplanesChat,
|
|
@@ -45260,9 +45490,425 @@ var ALL_EXAMPLE_CHATS = [
|
|
|
45260
45490
|
berlinAiFounderMeetupsMapChat,
|
|
45261
45491
|
deutschlandticketTrainFareBreakdownChat,
|
|
45262
45492
|
berlinMitteWorkFriendlyRestaurantsChat,
|
|
45263
|
-
openMeteoWeatherNotebookChat
|
|
45493
|
+
openMeteoWeatherNotebookChat,
|
|
45494
|
+
audioGenerateProductSuccessChimeChat,
|
|
45495
|
+
audioSpeakFriendlyWelcomeMessageChat
|
|
45264
45496
|
].sort((a, b) => a.metadata.order - b.metadata.order);
|
|
45265
45497
|
|
|
45498
|
+
// ../ui/src/demo_chats/exampleChatFiles.ts
|
|
45499
|
+
var FILE_LIKE_TYPES = /* @__PURE__ */ new Set([
|
|
45500
|
+
"audio",
|
|
45501
|
+
"audio-recording",
|
|
45502
|
+
"code",
|
|
45503
|
+
"code-code",
|
|
45504
|
+
"design",
|
|
45505
|
+
"diagram",
|
|
45506
|
+
"docs",
|
|
45507
|
+
"docs-doc",
|
|
45508
|
+
"document",
|
|
45509
|
+
"image",
|
|
45510
|
+
"images-image",
|
|
45511
|
+
"mind-map",
|
|
45512
|
+
"mind_map",
|
|
45513
|
+
"model3d",
|
|
45514
|
+
"music",
|
|
45515
|
+
"notebook",
|
|
45516
|
+
"pcb_schematic",
|
|
45517
|
+
"pdf",
|
|
45518
|
+
"recording",
|
|
45519
|
+
"remotion-video",
|
|
45520
|
+
"sheet",
|
|
45521
|
+
"sheets",
|
|
45522
|
+
"sheets-sheet",
|
|
45523
|
+
"spreadsheet",
|
|
45524
|
+
"svg",
|
|
45525
|
+
"video"
|
|
45526
|
+
]);
|
|
45527
|
+
var URL_FIELDS = [
|
|
45528
|
+
"downloadUrl",
|
|
45529
|
+
"download_url",
|
|
45530
|
+
"file_url",
|
|
45531
|
+
"previewAudioUrl",
|
|
45532
|
+
"preview_audio_url",
|
|
45533
|
+
"previewImageUrl",
|
|
45534
|
+
"preview_image_url",
|
|
45535
|
+
"previewVideoUrl",
|
|
45536
|
+
"preview_video_url",
|
|
45537
|
+
"src",
|
|
45538
|
+
"url",
|
|
45539
|
+
"video_url"
|
|
45540
|
+
];
|
|
45541
|
+
var AUDIO_URL_FIELDS = [
|
|
45542
|
+
"downloadUrl",
|
|
45543
|
+
"download_url",
|
|
45544
|
+
"file_url",
|
|
45545
|
+
"previewAudioUrl",
|
|
45546
|
+
"preview_audio_url",
|
|
45547
|
+
"src",
|
|
45548
|
+
"url"
|
|
45549
|
+
];
|
|
45550
|
+
var VIDEO_URL_FIELDS = [
|
|
45551
|
+
"downloadUrl",
|
|
45552
|
+
"download_url",
|
|
45553
|
+
"file_url",
|
|
45554
|
+
"previewVideoUrl",
|
|
45555
|
+
"preview_video_url",
|
|
45556
|
+
"video_url",
|
|
45557
|
+
"src",
|
|
45558
|
+
"url",
|
|
45559
|
+
"previewImageUrl",
|
|
45560
|
+
"preview_image_url"
|
|
45561
|
+
];
|
|
45562
|
+
var IMAGE_URL_FIELDS = [
|
|
45563
|
+
"downloadUrl",
|
|
45564
|
+
"download_url",
|
|
45565
|
+
"file_url",
|
|
45566
|
+
"previewImageUrl",
|
|
45567
|
+
"preview_image_url",
|
|
45568
|
+
"src",
|
|
45569
|
+
"url"
|
|
45570
|
+
];
|
|
45571
|
+
var FILENAME_FIELDS = [
|
|
45572
|
+
"filename",
|
|
45573
|
+
"file_name",
|
|
45574
|
+
"file_path",
|
|
45575
|
+
"original_filename"
|
|
45576
|
+
];
|
|
45577
|
+
var MIME_EXTENSION = {
|
|
45578
|
+
"application/pdf": "pdf",
|
|
45579
|
+
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": "xlsx",
|
|
45580
|
+
"application/vnd.openxmlformats-officedocument.wordprocessingml.document": "docx",
|
|
45581
|
+
"audio/mpeg": "mp3",
|
|
45582
|
+
"audio/wav": "wav",
|
|
45583
|
+
"image/jpeg": "jpg",
|
|
45584
|
+
"image/png": "png",
|
|
45585
|
+
"image/svg+xml": "svg",
|
|
45586
|
+
"image/webp": "webp",
|
|
45587
|
+
"model/gltf-binary": "glb",
|
|
45588
|
+
"text/html": "html",
|
|
45589
|
+
"text/markdown": "md",
|
|
45590
|
+
"text/plain": "txt",
|
|
45591
|
+
"video/mp4": "mp4"
|
|
45592
|
+
};
|
|
45593
|
+
function isRecord2(value) {
|
|
45594
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
45595
|
+
}
|
|
45596
|
+
function normalizeEmbedId(embedId) {
|
|
45597
|
+
return embedId.startsWith("embed:") ? embedId.slice("embed:".length) : embedId;
|
|
45598
|
+
}
|
|
45599
|
+
function cleanString(value) {
|
|
45600
|
+
if (typeof value !== "string") return "";
|
|
45601
|
+
const trimmed = stripQuotes(value.trim());
|
|
45602
|
+
if (!trimmed || trimmed === "null" || trimmed === "undefined") return "";
|
|
45603
|
+
return trimmed;
|
|
45604
|
+
}
|
|
45605
|
+
function stripQuotes(value) {
|
|
45606
|
+
const first = value[0];
|
|
45607
|
+
if ((first === '"' || first === "'") && value.endsWith(first)) {
|
|
45608
|
+
return value.slice(1, -1).replace(/\\n/g, "\n").replace(/\\"/g, '"').replace(/\\'/g, "'");
|
|
45609
|
+
}
|
|
45610
|
+
return value;
|
|
45611
|
+
}
|
|
45612
|
+
function numberValue2(value) {
|
|
45613
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
45614
|
+
if (typeof value !== "string" || value.trim() === "") return null;
|
|
45615
|
+
const parsed = Number(value);
|
|
45616
|
+
return Number.isFinite(parsed) ? parsed : null;
|
|
45617
|
+
}
|
|
45618
|
+
function parseFlatToonFields(content) {
|
|
45619
|
+
const fields = {};
|
|
45620
|
+
for (const line of content.split("\n")) {
|
|
45621
|
+
if (!line || /^\s/.test(line)) continue;
|
|
45622
|
+
const separatorIndex = line.indexOf(":");
|
|
45623
|
+
if (separatorIndex <= 0) continue;
|
|
45624
|
+
const key = line.slice(0, separatorIndex).trim();
|
|
45625
|
+
const value = line.slice(separatorIndex + 1).trim();
|
|
45626
|
+
if (!key || value === "") continue;
|
|
45627
|
+
fields[key] = stripQuotes(value);
|
|
45628
|
+
}
|
|
45629
|
+
return fields;
|
|
45630
|
+
}
|
|
45631
|
+
function decodeEmbedContent(content) {
|
|
45632
|
+
if (isRecord2(content)) return { ...content };
|
|
45633
|
+
if (typeof content !== "string" || !content.trim()) return {};
|
|
45634
|
+
const trimmed = content.trim();
|
|
45635
|
+
if (trimmed.startsWith("{") || trimmed.startsWith("[")) {
|
|
45636
|
+
try {
|
|
45637
|
+
const parsed = JSON.parse(trimmed);
|
|
45638
|
+
return isRecord2(parsed) ? parsed : {};
|
|
45639
|
+
} catch {
|
|
45640
|
+
return parseFlatToonFields(content);
|
|
45641
|
+
}
|
|
45642
|
+
}
|
|
45643
|
+
return parseFlatToonFields(content);
|
|
45644
|
+
}
|
|
45645
|
+
function stringField2(record, keys) {
|
|
45646
|
+
for (const key of keys) {
|
|
45647
|
+
const value = cleanString(record[key]);
|
|
45648
|
+
if (value) return value;
|
|
45649
|
+
}
|
|
45650
|
+
return "";
|
|
45651
|
+
}
|
|
45652
|
+
function basenameFromUrl(url) {
|
|
45653
|
+
if (url.startsWith("data:")) return "";
|
|
45654
|
+
const withoutQuery = url.split(/[?#]/)[0] || "";
|
|
45655
|
+
return withoutQuery.split("/").pop()?.replace(/[^a-zA-Z0-9._-]/g, "_") ?? "";
|
|
45656
|
+
}
|
|
45657
|
+
function extensionFromUrl(url) {
|
|
45658
|
+
const basename4 = basenameFromUrl(url);
|
|
45659
|
+
const dotIndex = basename4.lastIndexOf(".");
|
|
45660
|
+
return dotIndex > 0 ? basename4.slice(dotIndex + 1).toLowerCase() : "";
|
|
45661
|
+
}
|
|
45662
|
+
function extensionFromLanguage(language) {
|
|
45663
|
+
const normalized = language.toLowerCase();
|
|
45664
|
+
const map = {
|
|
45665
|
+
bash: "sh",
|
|
45666
|
+
css: "css",
|
|
45667
|
+
dockerfile: "Dockerfile",
|
|
45668
|
+
html: "html",
|
|
45669
|
+
javascript: "js",
|
|
45670
|
+
json: "json",
|
|
45671
|
+
markdown: "md",
|
|
45672
|
+
python: "py",
|
|
45673
|
+
rust: "rs",
|
|
45674
|
+
svelte: "svelte",
|
|
45675
|
+
text: "txt",
|
|
45676
|
+
typescript: "ts",
|
|
45677
|
+
yaml: "yml"
|
|
45678
|
+
};
|
|
45679
|
+
return (map[normalized] ?? normalized.replace(/[^a-z0-9]/g, "")) || "txt";
|
|
45680
|
+
}
|
|
45681
|
+
function nestedFormatFromToon(content) {
|
|
45682
|
+
if (typeof content !== "string") return "";
|
|
45683
|
+
const match = content.match(/\n\s+format:\s*([^\n]+)/);
|
|
45684
|
+
return cleanString(match?.[1]);
|
|
45685
|
+
}
|
|
45686
|
+
function urlForType(type, record) {
|
|
45687
|
+
if (type.includes("video") || type === "remotion-video") return stringField2(record, VIDEO_URL_FIELDS);
|
|
45688
|
+
if (type.includes("audio") || type === "music" || type === "recording") return stringField2(record, AUDIO_URL_FIELDS);
|
|
45689
|
+
if (type.includes("image") || type === "svg") return stringField2(record, IMAGE_URL_FIELDS);
|
|
45690
|
+
return stringField2(record, URL_FIELDS);
|
|
45691
|
+
}
|
|
45692
|
+
function inferFallbackExtension(type, record, content) {
|
|
45693
|
+
const mimeType = stringField2(record, ["mime_type", "file_type", "mimeType"]);
|
|
45694
|
+
if (mimeType && MIME_EXTENSION[mimeType]) return MIME_EXTENSION[mimeType];
|
|
45695
|
+
const urlExtension = extensionFromUrl(urlForType(type, record));
|
|
45696
|
+
if (urlExtension) return urlExtension;
|
|
45697
|
+
const nestedFormat = nestedFormatFromToon(content);
|
|
45698
|
+
if (nestedFormat) return nestedFormat;
|
|
45699
|
+
if (type.includes("video")) return "mp4";
|
|
45700
|
+
if (type.includes("audio") || type === "music" || type === "recording") return "mp3";
|
|
45701
|
+
if (type.includes("image")) return "png";
|
|
45702
|
+
if (type.includes("pdf")) return "pdf";
|
|
45703
|
+
if (type.includes("doc") || type === "document") return "docx";
|
|
45704
|
+
if (type.includes("sheet") || type === "spreadsheet") return "xlsx";
|
|
45705
|
+
if (type === "model3d") return "glb";
|
|
45706
|
+
if (type.includes("code") || type === "notebook" || type === "pcb_schematic") {
|
|
45707
|
+
return extensionFromLanguage(stringField2(record, ["language"]));
|
|
45708
|
+
}
|
|
45709
|
+
return "txt";
|
|
45710
|
+
}
|
|
45711
|
+
function inferTitle(embedId, type, record, content) {
|
|
45712
|
+
const url = urlForType(type, record);
|
|
45713
|
+
const urlBasename = basenameFromUrl(url);
|
|
45714
|
+
const filename = stringField2(record, FILENAME_FIELDS);
|
|
45715
|
+
if ((type.includes("video") || type === "music" || type === "audio") && urlBasename) {
|
|
45716
|
+
return urlBasename;
|
|
45717
|
+
}
|
|
45718
|
+
if (filename) return filename.replace(/[/\\]/g, "_");
|
|
45719
|
+
if (urlBasename) return urlBasename;
|
|
45720
|
+
const title = stringField2(record, ["title"]);
|
|
45721
|
+
if (title) {
|
|
45722
|
+
const extension2 = inferFallbackExtension(type, record, content);
|
|
45723
|
+
return `${title.replace(/[^a-zA-Z0-9._ -]/g, "_").trim()}.${extension2}`;
|
|
45724
|
+
}
|
|
45725
|
+
const extension = inferFallbackExtension(type, record, content);
|
|
45726
|
+
return `${type || "file"}-${embedId.slice(0, 8)}.${extension}`;
|
|
45727
|
+
}
|
|
45728
|
+
function inferNodeType(title, type) {
|
|
45729
|
+
const lowerTitle = title.toLowerCase();
|
|
45730
|
+
if (type.includes("pdf") || lowerTitle.endsWith(".pdf")) return "pdf";
|
|
45731
|
+
if (type.includes("image") || /\.(png|jpe?g|gif|webp|svg|avif|heic|heif)$/.test(lowerTitle)) return "image";
|
|
45732
|
+
if (type.includes("video") || /\.(mp4|mov|webm|m4v)$/.test(lowerTitle)) return "video";
|
|
45733
|
+
if (type.includes("audio") || type === "music" || type === "recording" || /\.(mp3|wav|m4a|ogg|webm)$/.test(lowerTitle)) return "recording";
|
|
45734
|
+
if (type.includes("sheet") || type === "spreadsheet" || /\.(csv|xlsx?|ods)$/.test(lowerTitle)) return "sheets-sheet";
|
|
45735
|
+
if (type.includes("doc") || type === "document" || /\.(docx?|odt|rtf)$/.test(lowerTitle)) return "docs-doc";
|
|
45736
|
+
if (type === "model3d" || /\.(glb|gltf|obj|stl)$/.test(lowerTitle)) return "model3d";
|
|
45737
|
+
if (type.includes("code") || type === "notebook" || type === "pcb_schematic") return "code-code";
|
|
45738
|
+
return "file";
|
|
45739
|
+
}
|
|
45740
|
+
function iconNameForNodeType(nodeType) {
|
|
45741
|
+
if (nodeType === "pdf") return "pdf";
|
|
45742
|
+
if (nodeType === "image") return "image";
|
|
45743
|
+
if (nodeType === "video") return "video";
|
|
45744
|
+
if (nodeType === "recording") return "audio";
|
|
45745
|
+
if (nodeType === "sheets-sheet") return "sheets";
|
|
45746
|
+
if (nodeType === "docs-doc") return "document";
|
|
45747
|
+
if (nodeType === "code-code") return "coding";
|
|
45748
|
+
if (nodeType === "model3d") return "3dmodels";
|
|
45749
|
+
return "files";
|
|
45750
|
+
}
|
|
45751
|
+
function labelForNodeType(nodeType, type) {
|
|
45752
|
+
if (nodeType === "pdf") return "PDF";
|
|
45753
|
+
if (nodeType === "image") return "Image";
|
|
45754
|
+
if (nodeType === "video") return "Video";
|
|
45755
|
+
if (nodeType === "recording") return type === "music" ? "Music" : "Audio";
|
|
45756
|
+
if (nodeType === "sheets-sheet") return "Sheet";
|
|
45757
|
+
if (nodeType === "docs-doc") return "Document";
|
|
45758
|
+
if (nodeType === "code-code") return type === "notebook" ? "Notebook" : "Code file";
|
|
45759
|
+
if (nodeType === "model3d") return "3D model";
|
|
45760
|
+
return "File";
|
|
45761
|
+
}
|
|
45762
|
+
function formatBytes(bytes) {
|
|
45763
|
+
if (!bytes || bytes <= 0) return "";
|
|
45764
|
+
if (bytes < 1024) return `${bytes} B`;
|
|
45765
|
+
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(bytes < 10 * 1024 ? 1 : 0)} KB`;
|
|
45766
|
+
return `${(bytes / (1024 * 1024)).toFixed(bytes < 10 * 1024 * 1024 ? 1 : 0)} MB`;
|
|
45767
|
+
}
|
|
45768
|
+
function plural(value, singular, pluralLabel = `${singular}s`) {
|
|
45769
|
+
return `${value} ${value === 1 ? singular : pluralLabel}`;
|
|
45770
|
+
}
|
|
45771
|
+
function buildMetadata(nodeType, type, record) {
|
|
45772
|
+
const parts = [labelForNodeType(nodeType, type)];
|
|
45773
|
+
const lineCount = numberValue2(record.line_count ?? record.lineCount);
|
|
45774
|
+
const pageCount = numberValue2(record.page_count ?? record.pageCount);
|
|
45775
|
+
const wordCount = numberValue2(record.word_count ?? record.wordCount);
|
|
45776
|
+
const duration = numberValue2(record.duration_seconds ?? record.durationSeconds);
|
|
45777
|
+
const size = numberValue2(record.byte_length ?? record.size_bytes ?? record.sizeBytes);
|
|
45778
|
+
if (lineCount) parts.push(plural(lineCount, "line"));
|
|
45779
|
+
if (pageCount) parts.push(plural(pageCount, "page"));
|
|
45780
|
+
if (wordCount) parts.push(plural(wordCount, "word"));
|
|
45781
|
+
if (duration) parts.push(`${duration.toFixed(duration < 10 ? 1 : 0)}s`);
|
|
45782
|
+
const sizeLabel = formatBytes(size);
|
|
45783
|
+
if (sizeLabel) parts.push(sizeLabel);
|
|
45784
|
+
return parts.join(" | ");
|
|
45785
|
+
}
|
|
45786
|
+
function isSupportedPublicUrl(url) {
|
|
45787
|
+
return url.startsWith("/") || url.startsWith("data:") || /^https?:\/\//i.test(url);
|
|
45788
|
+
}
|
|
45789
|
+
function extractEmbedIdsFromContent(content) {
|
|
45790
|
+
const decoded = decodeEmbedContent(content);
|
|
45791
|
+
const rawIds = decoded.embed_ids ?? decoded.embedIds;
|
|
45792
|
+
const ids = typeof rawIds === "string" ? rawIds.split(/[|,]/) : rawIds;
|
|
45793
|
+
if (!Array.isArray(ids)) return [];
|
|
45794
|
+
return ids.map((id) => cleanString(id)).filter(Boolean).map(normalizeEmbedId);
|
|
45795
|
+
}
|
|
45796
|
+
function buildEmbedLookup(embeds) {
|
|
45797
|
+
const lookup = /* @__PURE__ */ new Map();
|
|
45798
|
+
for (const embed of embeds) {
|
|
45799
|
+
if (!embed.embed_id) continue;
|
|
45800
|
+
lookup.set(normalizeEmbedId(embed.embed_id), embed);
|
|
45801
|
+
}
|
|
45802
|
+
return lookup;
|
|
45803
|
+
}
|
|
45804
|
+
function buildEmbedRefLookup(embeds) {
|
|
45805
|
+
const lookup = /* @__PURE__ */ new Map();
|
|
45806
|
+
for (const embed of embeds) {
|
|
45807
|
+
const embedId = normalizeEmbedId(embed.embed_id);
|
|
45808
|
+
lookup.set(embedId, embedId);
|
|
45809
|
+
lookup.set(`embed:${embedId}`, embedId);
|
|
45810
|
+
const decoded = decodeEmbedContent(embed.content);
|
|
45811
|
+
const embedRef = stringField2(decoded, ["embed_ref", "embedRef"]);
|
|
45812
|
+
if (embedRef) {
|
|
45813
|
+
lookup.set(embedRef, embedId);
|
|
45814
|
+
lookup.set(`embed:${embedRef}`, embedId);
|
|
45815
|
+
}
|
|
45816
|
+
}
|
|
45817
|
+
return lookup;
|
|
45818
|
+
}
|
|
45819
|
+
function extractReferencedExampleEmbedIds(messages, embeds) {
|
|
45820
|
+
const refLookup = buildEmbedRefLookup(embeds);
|
|
45821
|
+
const ids = /* @__PURE__ */ new Set();
|
|
45822
|
+
const jsonBlockRe = /```(?:json_embed|json)\s*([\s\S]*?)\s*```/g;
|
|
45823
|
+
const inlineEmbedRe = /embed:([a-zA-Z0-9_.:-]+)/g;
|
|
45824
|
+
for (const message of messages) {
|
|
45825
|
+
const content = message.content ?? "";
|
|
45826
|
+
for (const match of Array.from(content.matchAll(jsonBlockRe))) {
|
|
45827
|
+
try {
|
|
45828
|
+
const parsed = JSON.parse(match[1].trim());
|
|
45829
|
+
const embedId = cleanString(parsed.embed_id ?? parsed.embedId);
|
|
45830
|
+
const resolved = refLookup.get(embedId) ?? refLookup.get(`embed:${embedId}`) ?? embedId;
|
|
45831
|
+
if (resolved) ids.add(normalizeEmbedId(resolved));
|
|
45832
|
+
} catch {
|
|
45833
|
+
}
|
|
45834
|
+
}
|
|
45835
|
+
for (const match of Array.from(content.matchAll(inlineEmbedRe))) {
|
|
45836
|
+
const rawRef = match[1];
|
|
45837
|
+
const resolved = refLookup.get(rawRef) ?? refLookup.get(`embed:${rawRef}`) ?? rawRef;
|
|
45838
|
+
if (resolved) ids.add(normalizeEmbedId(resolved));
|
|
45839
|
+
}
|
|
45840
|
+
}
|
|
45841
|
+
return Array.from(ids);
|
|
45842
|
+
}
|
|
45843
|
+
function expandEmbedIds(embedIds, embeds) {
|
|
45844
|
+
const lookup = buildEmbedLookup(embeds);
|
|
45845
|
+
const seen = /* @__PURE__ */ new Set();
|
|
45846
|
+
const queue = [...embedIds.map(normalizeEmbedId)];
|
|
45847
|
+
while (queue.length > 0) {
|
|
45848
|
+
const embedId = queue.shift();
|
|
45849
|
+
if (!embedId || seen.has(embedId)) continue;
|
|
45850
|
+
seen.add(embedId);
|
|
45851
|
+
const embed = lookup.get(embedId);
|
|
45852
|
+
if (!embed) continue;
|
|
45853
|
+
const childIds = [
|
|
45854
|
+
...embed.embed_ids ?? [],
|
|
45855
|
+
...extractEmbedIdsFromContent(embed.content)
|
|
45856
|
+
];
|
|
45857
|
+
for (const childId of childIds) {
|
|
45858
|
+
const normalizedChildId = normalizeEmbedId(childId);
|
|
45859
|
+
if (normalizedChildId && !seen.has(normalizedChildId)) queue.push(normalizedChildId);
|
|
45860
|
+
}
|
|
45861
|
+
}
|
|
45862
|
+
return Array.from(seen);
|
|
45863
|
+
}
|
|
45864
|
+
function getEmbedFileReferences(embed) {
|
|
45865
|
+
const embedId = cleanString(embed.embed_id ?? embed.embedId ?? embed.id);
|
|
45866
|
+
if (!embedId) return [];
|
|
45867
|
+
const decoded = decodeEmbedContent(embed.content);
|
|
45868
|
+
const type = (stringField2(decoded, ["type", "embed_type", "embedType"]) || cleanString(embed.type) || "file").toLowerCase();
|
|
45869
|
+
if (!FILE_LIKE_TYPES.has(type)) return [];
|
|
45870
|
+
const title = inferTitle(embedId, type, decoded, embed.content);
|
|
45871
|
+
const nodeType = inferNodeType(title, type);
|
|
45872
|
+
const url = urlForType(type, decoded);
|
|
45873
|
+
const mimeType = stringField2(decoded, ["mime_type", "file_type", "mimeType"]);
|
|
45874
|
+
const createdAt = numberValue2(embed.created_at ?? embed.createdAt) ?? 0;
|
|
45875
|
+
return [{
|
|
45876
|
+
embedId: normalizeEmbedId(embedId),
|
|
45877
|
+
contentRef: `embed:${normalizeEmbedId(embedId)}`,
|
|
45878
|
+
title,
|
|
45879
|
+
subtitle: labelForNodeType(nodeType, type),
|
|
45880
|
+
type,
|
|
45881
|
+
nodeType,
|
|
45882
|
+
iconName: iconNameForNodeType(nodeType),
|
|
45883
|
+
createdAt,
|
|
45884
|
+
updatedAt: createdAt,
|
|
45885
|
+
metadata: buildMetadata(nodeType, type, decoded),
|
|
45886
|
+
appId: stringField2(decoded, ["app_id", "appId"]) || cleanString(embed.app_id ?? embed.appId) || null,
|
|
45887
|
+
skillId: stringField2(decoded, ["skill_id", "skillId"]) || cleanString(embed.skill_id ?? embed.skillId) || null,
|
|
45888
|
+
url: url && isSupportedPublicUrl(url) ? url : null,
|
|
45889
|
+
mimeType: mimeType || null
|
|
45890
|
+
}];
|
|
45891
|
+
}
|
|
45892
|
+
function collectExampleChatFileReferences(embeds, messages = []) {
|
|
45893
|
+
if (embeds.length === 0) return [];
|
|
45894
|
+
const lookup = buildEmbedLookup(embeds);
|
|
45895
|
+
const referencedIds = extractReferencedExampleEmbedIds(messages, embeds);
|
|
45896
|
+
const candidateIds = referencedIds.length > 0 ? expandEmbedIds(referencedIds, embeds) : embeds.map((embed) => normalizeEmbedId(embed.embed_id));
|
|
45897
|
+
const rows = [];
|
|
45898
|
+
const seen = /* @__PURE__ */ new Set();
|
|
45899
|
+
for (const embedId of candidateIds) {
|
|
45900
|
+
const embed = lookup.get(embedId);
|
|
45901
|
+
if (!embed) continue;
|
|
45902
|
+
for (const row of getEmbedFileReferences(embed)) {
|
|
45903
|
+
const key = `${row.embedId}:${row.title}`.toLowerCase();
|
|
45904
|
+
if (seen.has(key)) continue;
|
|
45905
|
+
rows.push(row);
|
|
45906
|
+
seen.add(key);
|
|
45907
|
+
}
|
|
45908
|
+
}
|
|
45909
|
+
return rows;
|
|
45910
|
+
}
|
|
45911
|
+
|
|
45266
45912
|
// ../ui/src/i18n/locales/en.json
|
|
45267
45913
|
var en_default = {
|
|
45268
45914
|
activity: {
|
|
@@ -53200,6 +53846,34 @@ Only output the final Markdown table. Do NOT include explanations, notes, or any
|
|
|
53200
53846
|
text: "[images-search] Show me more photos of the Orion spacecraft"
|
|
53201
53847
|
}
|
|
53202
53848
|
},
|
|
53849
|
+
audio_generate_product_success_chime: {
|
|
53850
|
+
title: {
|
|
53851
|
+
text: "Audio Generate Product Success Chime"
|
|
53852
|
+
},
|
|
53853
|
+
summary: {
|
|
53854
|
+
text: "Create a short product success chime with the Audio Generate app skill."
|
|
53855
|
+
},
|
|
53856
|
+
message_1: {
|
|
53857
|
+
text: "Create a short, friendly success chime for an OpenMates workflow finishing. Keep it clean, modern, and subtle enough for a product notification."
|
|
53858
|
+
},
|
|
53859
|
+
message_2: {
|
|
53860
|
+
text: '```json\n{"type":"app_skill_use","embed_id":"8d96310e-a05a-41e8-a687-08ce2ce1ce9a","app_id":"audio","skill_id":"generate"}\n```\n\nI created a short, friendly product success chime you can use as a subtle workflow-complete notification.'
|
|
53861
|
+
}
|
|
53862
|
+
},
|
|
53863
|
+
audio_speak_friendly_welcome_message: {
|
|
53864
|
+
title: {
|
|
53865
|
+
text: "Audio Speak Friendly Welcome Message"
|
|
53866
|
+
},
|
|
53867
|
+
summary: {
|
|
53868
|
+
text: "Turn a short welcome line into a friendly spoken message with the Audio Speak app skill."
|
|
53869
|
+
},
|
|
53870
|
+
message_1: {
|
|
53871
|
+
text: "Say this as a warm, natural welcome message: Welcome back to OpenMates. Your workspace is ready whenever you are."
|
|
53872
|
+
},
|
|
53873
|
+
message_2: {
|
|
53874
|
+
text: '```json\n{"type":"app_skill_use","embed_id":"463ace0f-02f9-43c2-94ee-cf385162bb75","app_id":"audio","skill_id":"speak"}\n```\n\nI generated the welcome line as a friendly spoken audio message.'
|
|
53875
|
+
}
|
|
53876
|
+
},
|
|
53203
53877
|
audio_transcribe_voice_note: {
|
|
53204
53878
|
title: {
|
|
53205
53879
|
text: "Transcribe a voice note"
|
|
@@ -66102,8 +66776,10 @@ function getExampleChatConversation(query) {
|
|
|
66102
66776
|
category: message.category ?? chat.category,
|
|
66103
66777
|
modelName: message.model_name ?? null,
|
|
66104
66778
|
createdAt: message.created_at,
|
|
66105
|
-
embedIds: []
|
|
66779
|
+
embedIds: extractReferencedExampleEmbedIds([message], chat.embeds)
|
|
66106
66780
|
})),
|
|
66781
|
+
embeds: chat.embeds,
|
|
66782
|
+
files: collectExampleChatFileReferences(chat.embeds, chat.messages),
|
|
66107
66783
|
followUpSuggestions: chat.follow_up_suggestions.map(translate)
|
|
66108
66784
|
};
|
|
66109
66785
|
}
|
|
@@ -69996,7 +70672,7 @@ async function requestProjectRemoteOperation(options) {
|
|
|
69996
70672
|
throw new ProjectRequesterError("source_offline", "The selected Project source is offline.");
|
|
69997
70673
|
}
|
|
69998
70674
|
const timeoutMs = options.timeoutMs ?? REMOTE_PROTOCOL_TIMEOUT_MS;
|
|
69999
|
-
let sourceSessionId =
|
|
70675
|
+
let sourceSessionId = stringField3(options.source, "source_session_id");
|
|
70000
70676
|
let keyEpoch = numberField(options.source, "key_epoch");
|
|
70001
70677
|
let routingIdentity = null;
|
|
70002
70678
|
if (!sourceSessionId || !keyEpoch) {
|
|
@@ -70148,7 +70824,7 @@ function parseJsonObject(value) {
|
|
|
70148
70824
|
}
|
|
70149
70825
|
throw new ProjectRequesterError("invalid_remote_payload", "The Project source returned an invalid payload.");
|
|
70150
70826
|
}
|
|
70151
|
-
function
|
|
70827
|
+
function stringField3(value, key) {
|
|
70152
70828
|
return typeof value[key] === "string" && value[key] ? value[key] : null;
|
|
70153
70829
|
}
|
|
70154
70830
|
function numberField(value, key) {
|
|
@@ -71081,7 +71757,7 @@ function splitTaskAskInstruction(instruction) {
|
|
|
71081
71757
|
const suffix = instruction.includes(":") ? instruction.split(":").slice(1).join(":") : instruction;
|
|
71082
71758
|
return suffix.split(/[,;]\s*/).map((title) => title.trim()).filter(Boolean).map((title) => ({ title }));
|
|
71083
71759
|
}
|
|
71084
|
-
function
|
|
71760
|
+
function isRecord3(value) {
|
|
71085
71761
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
71086
71762
|
}
|
|
71087
71763
|
function isPrivateCliOutputKey(key) {
|
|
@@ -71089,7 +71765,7 @@ function isPrivateCliOutputKey(key) {
|
|
|
71089
71765
|
}
|
|
71090
71766
|
function sanitizeWorkspaceAskOutput(value) {
|
|
71091
71767
|
if (Array.isArray(value)) return value.map((item) => sanitizeWorkspaceAskOutput(item));
|
|
71092
|
-
if (!
|
|
71768
|
+
if (!isRecord3(value)) return value;
|
|
71093
71769
|
const sanitized = {};
|
|
71094
71770
|
for (const [key, nested] of Object.entries(value)) {
|
|
71095
71771
|
if (isPrivateCliOutputKey(key)) continue;
|
|
@@ -71099,20 +71775,20 @@ function sanitizeWorkspaceAskOutput(value) {
|
|
|
71099
71775
|
}
|
|
71100
71776
|
async function prepareTaskAskOutput(result, masterKey) {
|
|
71101
71777
|
const output = sanitizeWorkspaceAskOutput(result);
|
|
71102
|
-
if (
|
|
71778
|
+
if (isRecord3(result.task)) {
|
|
71103
71779
|
output.task = taskToJson(await decryptUserTask(result.task, masterKey));
|
|
71104
71780
|
}
|
|
71105
|
-
if (Array.isArray(result.tasks) && result.tasks.every(
|
|
71781
|
+
if (Array.isArray(result.tasks) && result.tasks.every(isRecord3)) {
|
|
71106
71782
|
output.tasks = (await decryptUserTasks(result.tasks, masterKey)).map(taskToJson);
|
|
71107
71783
|
}
|
|
71108
71784
|
return output;
|
|
71109
71785
|
}
|
|
71110
71786
|
async function preparePlanAskOutput(result, masterKey) {
|
|
71111
71787
|
const output = sanitizeWorkspaceAskOutput(result);
|
|
71112
|
-
if (
|
|
71788
|
+
if (isRecord3(result.plan)) {
|
|
71113
71789
|
output.plan = planToJson(await decryptUserPlan(result.plan, masterKey));
|
|
71114
71790
|
}
|
|
71115
|
-
if (Array.isArray(result.plans) && result.plans.every(
|
|
71791
|
+
if (Array.isArray(result.plans) && result.plans.every(isRecord3)) {
|
|
71116
71792
|
output.plans = (await decryptUserPlans(result.plans, masterKey)).map(planToJson);
|
|
71117
71793
|
}
|
|
71118
71794
|
return output;
|
|
@@ -73426,6 +74102,28 @@ async function handleChats(client, subcommand, rest, flags, redactor) {
|
|
|
73426
74102
|
}
|
|
73427
74103
|
return;
|
|
73428
74104
|
}
|
|
74105
|
+
if (subcommand === "files") {
|
|
74106
|
+
const chatId = rest[0];
|
|
74107
|
+
if (!chatId) {
|
|
74108
|
+
throw new Error("Missing chat ID. Usage: openmates chats files <chat-id> [--json]");
|
|
74109
|
+
}
|
|
74110
|
+
const resolvedId = chatId.toLowerCase() === "last" ? "__last__" : chatId;
|
|
74111
|
+
if (apiKey) {
|
|
74112
|
+
throw new Error("Chat file listing through --api-key is not supported; use an authenticated CLI session so encrypted chat embeds can be decrypted locally.");
|
|
74113
|
+
}
|
|
74114
|
+
if (!client.hasSession()) {
|
|
74115
|
+
const example = resolveExampleChatForOpen(resolvedId === "__last__" ? "1" : resolvedId);
|
|
74116
|
+
if (!example) {
|
|
74117
|
+
throw new Error(`Example chat '${chatId}' not found. Run 'openmates chats list' to see available examples.`);
|
|
74118
|
+
}
|
|
74119
|
+
printChatFiles(example.chat, example.files, flags, { example: true });
|
|
74120
|
+
return;
|
|
74121
|
+
}
|
|
74122
|
+
const { chat, messages } = await client.getChatMessages(resolvedId, teamContext);
|
|
74123
|
+
const result = await loadChatFileReferencesForCli(client, messages);
|
|
74124
|
+
printChatFiles(chat, result.files, flags, { errors: result.errors });
|
|
74125
|
+
return;
|
|
74126
|
+
}
|
|
73429
74127
|
if (subcommand === "messages") {
|
|
73430
74128
|
const chatId = rest[0];
|
|
73431
74129
|
if (!chatId) {
|
|
@@ -74402,6 +75100,113 @@ function resolveExampleChatForOpen(target) {
|
|
|
74402
75100
|
}
|
|
74403
75101
|
return getExampleChatConversation(target);
|
|
74404
75102
|
}
|
|
75103
|
+
function collectMessageEmbedIdsForFiles(messages) {
|
|
75104
|
+
const ids = /* @__PURE__ */ new Set();
|
|
75105
|
+
const inlineEmbedRefRe = /embed:([a-zA-Z0-9_.:-]+)/g;
|
|
75106
|
+
for (const message of messages) {
|
|
75107
|
+
for (const embedId of message.embedIds ?? []) {
|
|
75108
|
+
if (embedId) ids.add(embedId);
|
|
75109
|
+
}
|
|
75110
|
+
for (const match of Array.from((message.content ?? "").matchAll(inlineEmbedRefRe))) {
|
|
75111
|
+
if (match[1]) ids.add(match[1]);
|
|
75112
|
+
}
|
|
75113
|
+
for (const segment of parseMessageSegments(message.content ?? "")) {
|
|
75114
|
+
if (segment.type === "embed" && segment.value) ids.add(segment.value);
|
|
75115
|
+
}
|
|
75116
|
+
}
|
|
75117
|
+
return Array.from(ids);
|
|
75118
|
+
}
|
|
75119
|
+
function fileReferenceKey(file) {
|
|
75120
|
+
return `${file.embedId}:${file.title}`.toLowerCase();
|
|
75121
|
+
}
|
|
75122
|
+
function chatFileReferenceFromEmbed(embed) {
|
|
75123
|
+
return getEmbedFileReferences({
|
|
75124
|
+
embedId: embed.embedId,
|
|
75125
|
+
type: embed.type,
|
|
75126
|
+
content: embed.content,
|
|
75127
|
+
appId: embed.appId,
|
|
75128
|
+
skillId: embed.skillId,
|
|
75129
|
+
createdAt: embed.createdAt
|
|
75130
|
+
});
|
|
75131
|
+
}
|
|
75132
|
+
async function loadChatFileReferencesForCli(client, messages) {
|
|
75133
|
+
const queue = collectMessageEmbedIdsForFiles(messages);
|
|
75134
|
+
const visitedEmbeds = /* @__PURE__ */ new Set();
|
|
75135
|
+
const seenFiles = /* @__PURE__ */ new Set();
|
|
75136
|
+
const files = [];
|
|
75137
|
+
const errors = [];
|
|
75138
|
+
while (queue.length > 0) {
|
|
75139
|
+
const embedId = queue.shift();
|
|
75140
|
+
if (!embedId || visitedEmbeds.has(embedId)) continue;
|
|
75141
|
+
visitedEmbeds.add(embedId);
|
|
75142
|
+
try {
|
|
75143
|
+
const embed = await client.getEmbed(embedId);
|
|
75144
|
+
for (const file of chatFileReferenceFromEmbed(embed)) {
|
|
75145
|
+
const key = fileReferenceKey(file);
|
|
75146
|
+
if (seenFiles.has(key)) continue;
|
|
75147
|
+
files.push(file);
|
|
75148
|
+
seenFiles.add(key);
|
|
75149
|
+
}
|
|
75150
|
+
for (const childId of extractEmbedIdsFromContent(embed.content)) {
|
|
75151
|
+
if (childId && !visitedEmbeds.has(childId)) queue.push(childId);
|
|
75152
|
+
}
|
|
75153
|
+
} catch (error) {
|
|
75154
|
+
errors.push({
|
|
75155
|
+
embed_id: embedId,
|
|
75156
|
+
message: error instanceof Error ? error.message : String(error)
|
|
75157
|
+
});
|
|
75158
|
+
}
|
|
75159
|
+
}
|
|
75160
|
+
return { files, errors };
|
|
75161
|
+
}
|
|
75162
|
+
function chatFileToJson(file) {
|
|
75163
|
+
return {
|
|
75164
|
+
embed_id: file.embedId,
|
|
75165
|
+
content_ref: file.contentRef,
|
|
75166
|
+
title: file.title,
|
|
75167
|
+
type: file.type,
|
|
75168
|
+
node_type: file.nodeType,
|
|
75169
|
+
metadata: file.metadata,
|
|
75170
|
+
app_id: file.appId,
|
|
75171
|
+
skill_id: file.skillId,
|
|
75172
|
+
url: file.url,
|
|
75173
|
+
mime_type: file.mimeType
|
|
75174
|
+
};
|
|
75175
|
+
}
|
|
75176
|
+
function printChatFiles(chat, files, flags, options = {}) {
|
|
75177
|
+
if (flags.json === true) {
|
|
75178
|
+
printJson2({
|
|
75179
|
+
chat_id: chat.id,
|
|
75180
|
+
title: chat.title,
|
|
75181
|
+
source: options.example ? "example" : "chat",
|
|
75182
|
+
count: files.length,
|
|
75183
|
+
files: files.map(chatFileToJson),
|
|
75184
|
+
errors: options.errors ?? []
|
|
75185
|
+
});
|
|
75186
|
+
return;
|
|
75187
|
+
}
|
|
75188
|
+
const title = chat.title ?? chat.shortId ?? chat.id;
|
|
75189
|
+
header(`Files for ${title}`);
|
|
75190
|
+
if (options.example) {
|
|
75191
|
+
process.stdout.write("\x1B[2mPublic example chat files are resolved from bundled static embed metadata.\x1B[0m\n");
|
|
75192
|
+
}
|
|
75193
|
+
if (files.length === 0) {
|
|
75194
|
+
process.stdout.write("\x1B[2mNo files found for this chat.\x1B[0m\n");
|
|
75195
|
+
} else {
|
|
75196
|
+
for (const file of files) {
|
|
75197
|
+
const appSkill = [file.appId, file.skillId].filter(Boolean).join("/");
|
|
75198
|
+
const suffix = appSkill ? ` \x1B[2m${appSkill}\x1B[0m` : "";
|
|
75199
|
+
process.stdout.write(` \x1B[1m${file.title}\x1B[0m \x1B[2m${file.metadata}\x1B[0m${suffix}
|
|
75200
|
+
`);
|
|
75201
|
+
process.stdout.write(` \x1B[2m${file.contentRef}${file.url ? ` ${file.url}` : ""}\x1B[0m
|
|
75202
|
+
`);
|
|
75203
|
+
}
|
|
75204
|
+
}
|
|
75205
|
+
for (const error of options.errors ?? []) {
|
|
75206
|
+
process.stderr.write(`Warning: could not inspect embed ${error.embed_id}: ${error.message}
|
|
75207
|
+
`);
|
|
75208
|
+
}
|
|
75209
|
+
}
|
|
74405
75210
|
async function openUrl(url) {
|
|
74406
75211
|
const { exec: exec2 } = await import("child_process");
|
|
74407
75212
|
const platform4 = process.platform;
|
|
@@ -80436,6 +81241,7 @@ function printChatsHelp() {
|
|
|
80436
81241
|
openmates chats list [--limit <n>] [--page <n>] [--json]
|
|
80437
81242
|
openmates chats show <chat-id> [--raw] [--json] [--all]
|
|
80438
81243
|
openmates chats messages <chat-id> [--json]
|
|
81244
|
+
openmates chats files <chat-id> [--json]
|
|
80439
81245
|
openmates chats <chat-id> add-to-project <project-id> [--folder <folder-id>] [--openmates-only|--repo-copy|--remote-cache-copy|--remote-copy] [--json]
|
|
80440
81246
|
openmates chats <chat-id> remove-from-project <project-id> [--json]
|
|
80441
81247
|
openmates chats fork <chat-id> --from-message <message-id> [--title <title>] [--json]
|
|
@@ -80463,6 +81269,11 @@ Options for 'show':
|
|
|
80463
81269
|
--raw Show raw decrypted message content without rendering embeds
|
|
80464
81270
|
or cleaning embed references. Useful for debugging.
|
|
80465
81271
|
|
|
81272
|
+
Options for 'files':
|
|
81273
|
+
Lists uploaded and generated files connected to a saved or public example chat.
|
|
81274
|
+
Saved chats require an authenticated CLI session so encrypted embeds can be
|
|
81275
|
+
decrypted locally. Public examples also work while logged out.
|
|
81276
|
+
|
|
80466
81277
|
Options for 'fork', 'rewind', and 'retry':
|
|
80467
81278
|
--from-message <id> Message boundary for non-destructive fork.
|
|
80468
81279
|
--to-message <id> Message boundary to keep when rewinding.
|
|
@@ -80540,6 +81351,8 @@ Examples:
|
|
|
80540
81351
|
openmates chats open gigantic-airplanes-transporting-rocket-parts
|
|
80541
81352
|
openmates chats show d262cb68
|
|
80542
81353
|
openmates chats messages d262cb68
|
|
81354
|
+
openmates chats files d262cb68
|
|
81355
|
+
openmates chats files example-audio-speak-friendly-welcome-message --json
|
|
80543
81356
|
openmates chats fork d262cb68 --from-message 8f4e2a1c --title "Clean branch"
|
|
80544
81357
|
openmates chats rewind d262cb68 --to-message 8f4e2a1c --send "Continue from here" --yes
|
|
80545
81358
|
openmates chats retry d262cb68 --yes
|
package/dist/cli.js
CHANGED
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -113,7 +113,8 @@ services:
|
|
|
113
113
|
test: ["CMD", "/usr/local/bin/openmates-directus-health"]
|
|
114
114
|
interval: 10s
|
|
115
115
|
timeout: 8s
|
|
116
|
-
|
|
116
|
+
# cms-setup creates the indexes validated by this health script; cold CI runners can take several minutes.
|
|
117
|
+
start_period: 10m
|
|
117
118
|
retries: 12
|
|
118
119
|
|
|
119
120
|
cms-database:
|
|
@@ -225,12 +226,25 @@ services:
|
|
|
225
226
|
mem_limit: ${CORE_WORKER_MEMORY_LIMIT:-3g}
|
|
226
227
|
environment:
|
|
227
228
|
<<: *openmates-worker-env
|
|
228
|
-
CELERY_QUEUES: persistence,health_check,server_stats,demo,e2e_tests,
|
|
229
|
+
CELERY_QUEUES: persistence,health_check,server_stats,demo,e2e_tests,push
|
|
229
230
|
CELERY_AUTOSCALE_MAX: ${CORE_WORKER_CONCURRENCY:-${CELERY_AUTOSCALE_MAX:-3}}
|
|
230
231
|
CELERY_AUTOSCALE_MIN: ${CELERY_AUTOSCALE_MIN:-1}
|
|
231
232
|
CELERY_METRICS_PORT: "9109"
|
|
232
233
|
command: >
|
|
233
|
-
sh -c "chown -R celeryuser:celeryuser /vault-data && gosu celeryuser python -m celery -A backend.core.api.app.tasks.celery_config worker --loglevel=info --queues=persistence,health_check,server_stats,demo,e2e_tests,
|
|
234
|
+
sh -c "chown -R celeryuser:celeryuser /vault-data && gosu celeryuser python -m celery -A backend.core.api.app.tasks.celery_config worker --loglevel=info --queues=persistence,health_check,server_stats,demo,e2e_tests,push --concurrency=$${CELERY_AUTOSCALE_MAX} --max-tasks-per-child=50 --max-memory-per-child=600000 --prefetch-multiplier=1"
|
|
235
|
+
|
|
236
|
+
reminder-worker:
|
|
237
|
+
<<: *openmates-worker-base
|
|
238
|
+
container_name: reminder-worker
|
|
239
|
+
mem_limit: ${REMINDER_WORKER_MEMORY_LIMIT:-1536m}
|
|
240
|
+
environment:
|
|
241
|
+
<<: *openmates-worker-env
|
|
242
|
+
CELERY_QUEUES: reminder
|
|
243
|
+
CELERY_AUTOSCALE_MAX: ${REMINDER_WORKER_CONCURRENCY:-2}
|
|
244
|
+
CELERY_AUTOSCALE_MIN: ${CELERY_AUTOSCALE_MIN:-1}
|
|
245
|
+
CELERY_METRICS_PORT: "9111"
|
|
246
|
+
command: >
|
|
247
|
+
sh -c "chown -R celeryuser:celeryuser /vault-data && gosu celeryuser python -m celery -A backend.core.api.app.tasks.celery_config worker --loglevel=info --queues=reminder --concurrency=$${CELERY_AUTOSCALE_MAX} --max-tasks-per-child=50 --max-memory-per-child=600000 --prefetch-multiplier=1"
|
|
234
248
|
|
|
235
249
|
workflow-worker:
|
|
236
250
|
<<: *openmates-worker-base
|