openmates 0.12.0-alpha.18 → 0.12.0-alpha.19

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.
@@ -8587,6 +8587,13 @@ var IMAGE_CHANNEL_TAGS = {
8587
8587
  main: MAIN_BRANCH,
8588
8588
  dev: DEV_BRANCH
8589
8589
  };
8590
+ var BACKEND_CONFIG_FILE = join3("backend", "config", "backend_config.yml");
8591
+ var OFF_BY_DEFAULT_FEATURES = /* @__PURE__ */ new Map([
8592
+ ["embed:code:application", "Application previews are still unstable"],
8593
+ ["platform:projects", "Projects workspace is not ready by default"],
8594
+ ["platform:workflows", "Workflows workspace is not implemented yet"],
8595
+ ["platform:tasks", "Tasks workspace is not implemented yet"]
8596
+ ]);
8590
8597
  var MINIMAL_ENV_TEMPLATE = `# OpenMates self-host image-mode environment
8591
8598
  SECRET__MISTRAL_AI__API_KEY=
8592
8599
  SECRET__CEREBRAS__API_KEY=
@@ -8674,6 +8681,65 @@ function getInstallMode(installPath, config = loadConfigForInstallPath(installPa
8674
8681
  function shouldPullImages() {
8675
8682
  return process.env.OPENMATES_SKIP_IMAGE_PULL !== "1";
8676
8683
  }
8684
+ function normalizeFeatureList(items) {
8685
+ const seen = /* @__PURE__ */ new Set();
8686
+ const normalized = [];
8687
+ for (const item of items) {
8688
+ const value = item.trim();
8689
+ if (!value || seen.has(value)) continue;
8690
+ seen.add(value);
8691
+ normalized.push(value);
8692
+ }
8693
+ return normalized;
8694
+ }
8695
+ function parseListBlock(content, key) {
8696
+ const match = content.match(new RegExp(`^${key}:\\n((?:[ \\t]+.*\\n?)*)`, "m"));
8697
+ if (!match) return [];
8698
+ const block = match[1] ?? "";
8699
+ return normalizeFeatureList(
8700
+ [...block.matchAll(/^\s*-\s*["']?([^"'\n#]+)["']?/gm)].map((item) => item[1] ?? "")
8701
+ );
8702
+ }
8703
+ function parseFeatureOverrides(content) {
8704
+ const overridesMatch = content.match(/^feature_overrides:\n((?:[ \t]+.*\n?)*)/m);
8705
+ const overridesBlock = overridesMatch?.[1] ?? "";
8706
+ const enabled = parseListBlock(overridesBlock.replace(/^ {2}/gm, ""), "enabled");
8707
+ const disabled = parseListBlock(overridesBlock.replace(/^ {2}/gm, ""), "disabled");
8708
+ const legacyDisabledApps = parseListBlock(content, "disabled_apps").map(
8709
+ (appId) => appId.startsWith("app:") ? appId : `app:${appId}`
8710
+ );
8711
+ return {
8712
+ enabled: normalizeFeatureList(enabled),
8713
+ disabled: normalizeFeatureList([...disabled, ...legacyDisabledApps])
8714
+ };
8715
+ }
8716
+ function renderFeatureOverrides(overrides) {
8717
+ const renderList = (key, items) => {
8718
+ if (!items.length) return ` ${key}: []`;
8719
+ return [` ${key}:`, ...items.map((item) => ` - "${item}"`)].join("\n");
8720
+ };
8721
+ return [
8722
+ "# Admin feature overrides. Changes require a server restart.",
8723
+ "feature_overrides:",
8724
+ renderList("enabled", overrides.enabled),
8725
+ renderList("disabled", overrides.disabled),
8726
+ ""
8727
+ ].join("\n");
8728
+ }
8729
+ function removeConfigBlock(content, key) {
8730
+ return content.replace(new RegExp(`(?:^|\\n)#.*\\n${key}:\\n(?:[ \\t]+.*\\n?)*`, "m"), "\n").replace(new RegExp(`^${key}:\\n(?:[ \\t]+.*\\n?)*`, "m"), "");
8731
+ }
8732
+ function updateFeatureOverridesContent(content, overrides) {
8733
+ let next = removeConfigBlock(content, "feature_overrides");
8734
+ next = removeConfigBlock(next, "disabled_apps");
8735
+ next = next.trimEnd();
8736
+ return `${next}
8737
+
8738
+ ${renderFeatureOverrides(overrides)}`;
8739
+ }
8740
+ function featureKind(featureId) {
8741
+ return featureId.split(":", 1)[0] || "unknown";
8742
+ }
8677
8743
  function composeArgs(installPath, withOverrides, installMode = getInstallMode(installPath)) {
8678
8744
  const composeFile = installMode === "image" ? IMAGE_COMPOSE_FILE : SOURCE_COMPOSE_FILE;
8679
8745
  const args = ["compose", "--env-file", ".env", "-f", composeFile];
@@ -9383,6 +9449,70 @@ async function serverMakeAdmin(rest, flags) {
9383
9449
  console.log(`Admin privileges granted to ${email}.`);
9384
9450
  }
9385
9451
  }
9452
+ async function serverFeatures(rest, flags) {
9453
+ const action = rest[0] ?? "list";
9454
+ const featureId = rest[1];
9455
+ const installPath = resolveServerPath(flags);
9456
+ const configPath = join3(installPath, BACKEND_CONFIG_FILE);
9457
+ if (!existsSync5(configPath)) {
9458
+ throw new Error(`Backend config not found at ${configPath}. Run 'openmates server install' first or pass --path <dir>.`);
9459
+ }
9460
+ const content = readFileSync5(configPath, "utf-8");
9461
+ const overrides = parseFeatureOverrides(content);
9462
+ const writeOverrides = (nextOverrides) => {
9463
+ writeFileSync3(configPath, updateFeatureOverridesContent(content, nextOverrides));
9464
+ console.log(`Updated ${configPath}`);
9465
+ console.log("Restart the server for feature changes to take effect: openmates server restart");
9466
+ };
9467
+ if (action === "list") {
9468
+ console.log("Feature overrides:");
9469
+ console.log(` enabled: ${overrides.enabled.length ? overrides.enabled.join(", ") : "none"}`);
9470
+ console.log(` disabled: ${overrides.disabled.length ? overrides.disabled.join(", ") : "none"}`);
9471
+ console.log("\nKnown off-by-default features:");
9472
+ for (const [id, reason] of OFF_BY_DEFAULT_FEATURES.entries()) {
9473
+ const override = overrides.enabled.includes(id) ? "enabled override" : overrides.disabled.includes(id) ? "disabled override" : "default off";
9474
+ console.log(` ${id} (${featureKind(id)}): ${override} - ${reason}`);
9475
+ }
9476
+ return;
9477
+ }
9478
+ if (!featureId) {
9479
+ throw new Error(`Usage: openmates server features ${action} <feature-id>`);
9480
+ }
9481
+ if (action === "enable") {
9482
+ writeOverrides({
9483
+ enabled: normalizeFeatureList([...overrides.enabled, featureId]),
9484
+ disabled: overrides.disabled.filter((id) => id !== featureId)
9485
+ });
9486
+ return;
9487
+ }
9488
+ if (action === "disable") {
9489
+ writeOverrides({
9490
+ enabled: overrides.enabled.filter((id) => id !== featureId),
9491
+ disabled: normalizeFeatureList([...overrides.disabled, featureId])
9492
+ });
9493
+ return;
9494
+ }
9495
+ if (action === "reset") {
9496
+ writeOverrides({
9497
+ enabled: overrides.enabled.filter((id) => id !== featureId),
9498
+ disabled: overrides.disabled.filter((id) => id !== featureId)
9499
+ });
9500
+ return;
9501
+ }
9502
+ if (action === "explain") {
9503
+ const defaultReason = OFF_BY_DEFAULT_FEATURES.get(featureId);
9504
+ const override = overrides.enabled.includes(featureId) ? "enabled" : overrides.disabled.includes(featureId) ? "disabled" : "none";
9505
+ const defaultState = defaultReason ? "off" : "on";
9506
+ const effective = override === "enabled" ? "enabled" : override === "disabled" ? "disabled" : defaultState === "on" ? "enabled" : "disabled";
9507
+ console.log(`Feature: ${featureId}`);
9508
+ console.log(`Kind: ${featureKind(featureId)}`);
9509
+ console.log(`Default: ${defaultState}${defaultReason ? ` (${defaultReason})` : ""}`);
9510
+ console.log(`Override: ${override}`);
9511
+ console.log(`Effective after restart: ${effective}`);
9512
+ return;
9513
+ }
9514
+ throw new Error(`Unknown server features command '${action}'. Use list, enable, disable, reset, or explain.`);
9515
+ }
9386
9516
  async function serverUninstall(flags) {
9387
9517
  requireDocker();
9388
9518
  const installPath = resolveServerPath(flags);
@@ -9494,11 +9624,20 @@ Command Options:
9494
9624
  make-admin:
9495
9625
  openmates server make-admin <email>
9496
9626
 
9627
+ features:
9628
+ openmates server features list
9629
+ openmates server features enable <feature-id>
9630
+ openmates server features disable <feature-id>
9631
+ openmates server features reset <feature-id>
9632
+ openmates server features explain <feature-id>
9633
+
9497
9634
  Examples:
9498
9635
  openmates server install
9499
9636
  openmates server start --with-overrides
9500
9637
  openmates server logs --container api --follow
9501
9638
  openmates server make-admin user@example.com
9639
+ openmates server features disable app:videos
9640
+ openmates server features enable embed:code:application
9502
9641
  openmates server update
9503
9642
  openmates server update --dry-run
9504
9643
  openmates server update --image-tag v0.12.0-alpha.1
@@ -9530,6 +9669,8 @@ async function handleServer(subcommand, rest, flags) {
9530
9669
  return serverReset(flags);
9531
9670
  case "make-admin":
9532
9671
  return serverMakeAdmin(rest, flags);
9672
+ case "features":
9673
+ return serverFeatures(rest, flags);
9533
9674
  case "uninstall":
9534
9675
  return serverUninstall(flags);
9535
9676
  default:
package/dist/cli.js CHANGED
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  getExtForLang,
4
4
  serializeToYaml
5
- } from "./chunk-L5U4RDFT.js";
5
+ } from "./chunk-FTMMOTBN.js";
6
6
  import "./chunk-AXNRPVLE.js";
7
7
  export {
8
8
  getExtForLang,
package/dist/index.js CHANGED
@@ -9,7 +9,7 @@ import {
9
9
  deriveAppUrl,
10
10
  getExtForLang,
11
11
  serializeToYaml
12
- } from "./chunk-L5U4RDFT.js";
12
+ } from "./chunk-FTMMOTBN.js";
13
13
  import "./chunk-AXNRPVLE.js";
14
14
  export {
15
15
  ASSISTANT_FEEDBACK_REPORT_TITLE,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openmates",
3
- "version": "0.12.0-alpha.18",
3
+ "version": "0.12.0-alpha.19",
4
4
  "description": "OpenMates CLI and SDK",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",