// src/plugin-intent/intent-dispatcher.ts
import { Effect as Effect3, Option, pipe as pipe2, Ref as Ref2 } from "effect";
import { live as live2 } from "@dxos/live-object";
import { log as log3 } from "@dxos/log";
import { byPosition } from "@dxos/util";

// src/plugin-intent/actions.ts
import { Schema as Schema2 } from "effect";

// src/plugin-intent/intent.ts
import { Schema } from "effect";
var createIntent = (schema, data = {}, params = {}) => {
  const _ = Schema.validateSync(schema.fields.input)(data);
  const intent = {
    ...params,
    _schema: schema,
    id: schema._tag,
    data
  };
  return {
    first: intent,
    last: intent,
    all: [
      intent
    ]
  };
};
var chain = (schema, data = {}, params = {}) => (intent) => {
  const intents = "all" in intent ? intent.all : [
    intent
  ];
  const first = intents[0];
  const last = {
    ...params,
    _schema: schema,
    id: schema._tag,
    data
  };
  return {
    first,
    last,
    all: [
      ...intents,
      last
    ]
  };
};
var Label = Schema.Union(Schema.String, Schema.mutable(Schema.Tuple(Schema.String, Schema.mutable(Schema.Struct({
  ns: Schema.String,
  count: Schema.optional(Schema.Number),
  defaultValue: Schema.optional(Schema.String)
})))));

// src/plugin-intent/actions.ts
var INTENT_PLUGIN = "dxos.org/plugin/intent";
var INTENT_ACTION = `${INTENT_PLUGIN}/action`;
(function(IntentAction2) {
  class Track extends Schema2.TaggedClass()(`${INTENT_ACTION}/track`, {
    input: Schema2.Struct({
      intents: Schema2.Array(Schema2.String),
      error: Schema2.optional(Schema2.String)
    }),
    output: Schema2.Void
  }) {
  }
  IntentAction2.Track = Track;
  class ShowUndo extends Schema2.TaggedClass()(`${INTENT_ACTION}/show-undo`, {
    input: Schema2.Struct({
      message: Label
    }),
    output: Schema2.Void
  }) {
  }
  IntentAction2.ShowUndo = ShowUndo;
})(IntentAction || (IntentAction = {}));
var IntentAction;

// src/plugin-intent/errors.ts
var BaseError = class extends Error {
  constructor(code, message, context) {
    super(message ?? code, {
      cause: context
    }), this.code = code, this.context = context;
    this.name = code;
    Object.setPrototypeOf(this, new.target.prototype);
  }
};
var NoResolversError = class extends BaseError {
  constructor(action) {
    super("NO_RESOLVERS", "No resolvers were found for the action", {
      action
    });
  }
};
var CycleDetectedError = class extends BaseError {
  constructor(context) {
    super("CYCLE_DETECTED", "Intent execution limit exceeded. This is likely due to an infinite loop within intent resolvers.", context);
  }
};

// src/core/capabilities.ts
import { Rx } from "@effect-rx/rx-react";
import { Effect } from "effect";
import { Trigger } from "@dxos/async";
import { invariant } from "@dxos/invariant";
import { log } from "@dxos/log";
var __dxlog_file = "/__w/dxos/dxos/packages/sdk/app-framework/src/core/capabilities.ts";
var InterfaceDefTypeId = Symbol.for("InterfaceDefTypeId");
var defineCapability = (identifier) => {
  return {
    identifier
  };
};
var CapabilityImpl = class {
  constructor(moduleId, implementation) {
    this.moduleId = moduleId;
    this.implementation = implementation;
  }
};
var contributes = (interfaceDef, implementation, deactivate) => {
  return {
    interface: interfaceDef,
    implementation,
    deactivate
  };
};
var lazy = (c) => async (props) => {
  const { default: getCapability } = await c();
  return async () => getCapability(props);
};
var PluginContext = class {
  constructor({ registry, activate, reset }) {
    this._capabilityImpls = Rx.family(() => {
      return Rx.make([]).pipe(Rx.keepAlive);
    });
    this._capabilities = Rx.family((id) => {
      return Rx.make((get) => {
        const current = get(this._capabilityImpls(id));
        return current.map((c) => c.implementation);
      });
    });
    this._capability = Rx.family((id) => {
      return Rx.make((get) => {
        const current = get(this._capabilities(id));
        invariant(current.length > 0, `No capability found for ${id}`, {
          F: __dxlog_file,
          L: 117,
          S: this,
          A: [
            "current.length > 0",
            "`No capability found for ${id}`"
          ]
        });
        return current[0];
      });
    });
    this._registry = registry;
    this.activate = activate;
    this.reset = reset;
  }
  /**
  * @internal
  */
  contributeCapability({ module: moduleId, interface: interfaceDef, implementation }) {
    const current = this._registry.get(this._capabilityImpls(interfaceDef.identifier));
    const capability = new CapabilityImpl(moduleId, implementation);
    if (current.includes(capability)) {
      return;
    }
    this._registry.set(this._capabilityImpls(interfaceDef.identifier), [
      ...current,
      capability
    ]);
    log("capability contributed", {
      id: interfaceDef.identifier,
      moduleId,
      count: current.length
    }, {
      F: __dxlog_file,
      L: 161,
      S: this,
      C: (f, a) => f(...a)
    });
  }
  /**
  * @internal
  */
  removeCapability(interfaceDef, implementation) {
    const current = this._registry.get(this._capabilityImpls(interfaceDef.identifier));
    if (current.length === 0) {
      return;
    }
    const next = current.filter((c) => c.implementation !== implementation);
    if (next.length !== current.length) {
      this._registry.set(this._capabilityImpls(interfaceDef.identifier), next);
      log("capability removed", {
        id: interfaceDef.identifier,
        count: current.length
      }, {
        F: __dxlog_file,
        L: 180,
        S: this,
        C: (f, a) => f(...a)
      });
    } else {
      log.warn("capability not removed", {
        id: interfaceDef.identifier
      }, {
        F: __dxlog_file,
        L: 182,
        S: this,
        C: (f, a) => f(...a)
      });
    }
  }
  /**
  * Get the Rx reference to the available capabilities for a given interface.
  * Primarily useful for deriving other Rx values based on the capabilities or
  * for subscribing to changes in the capabilities.
  * @returns An Rx reference to the available capabilities.
  */
  capabilities(interfaceDef) {
    return this._capabilities(interfaceDef.identifier);
  }
  /**
  * Get the Rx reference to the available capabilities for a given interface.
  * Primarily useful for deriving other Rx values based on the capability or
  * for subscribing to changes in the capability.
  * @returns An Rx reference to the available capability.
  * @throws If no capability is found.
  */
  capability(interfaceDef) {
    return this._capability(interfaceDef.identifier);
  }
  /**
  * Get capabilities from the plugin context.
  * @returns An array of capabilities.
  */
  getCapabilities(interfaceDef) {
    return this._registry.get(this.capabilities(interfaceDef));
  }
  /**
  * Requests a single capability from the plugin context.
  * @returns The capability.
  * @throws If no capability is found.
  */
  getCapability(interfaceDef) {
    return this._registry.get(this.capability(interfaceDef));
  }
  /**
  * Waits for a capability to be available.
  * @returns The capability.
  */
  async waitForCapability(interfaceDef) {
    const [capability] = this.getCapabilities(interfaceDef);
    if (capability) {
      return capability;
    }
    const trigger = new Trigger();
    const cancel = this._registry.subscribe(this.capabilities(interfaceDef), (capabilities) => {
      if (capabilities.length > 0) {
        trigger.wake(capabilities[0]);
      }
    });
    const result = await trigger.wait();
    cancel();
    return result;
  }
  async activatePromise(event) {
    return this.activate(event).pipe(Effect.runPromise);
  }
  async resetPromise(event) {
    return this.reset(event).pipe(Effect.runPromise);
  }
};

// src/core/events.ts
var defineEvent = (id, specifier) => {
  return {
    id,
    specifier
  };
};
var eventKey = (event) => event.specifier ? `${event.id}:${event.specifier}` : event.id;
var oneOf = (...events) => ({
  type: "one-of",
  events
});
var allOf = (...events) => ({
  type: "all-of",
  events
});
var isOneOf = (events) => "type" in events && events.type === "one-of";
var isAllOf = (events) => "type" in events && events.type === "all-of";
var getEvents = (events) => "type" in events ? events.events : [
  events
];

// src/core/manager.ts
import { Registry } from "@effect-rx/rx-react";
import { untracked } from "@preact/signals-core";
import { Array as A, Effect as Effect2, Either, Match, pipe } from "effect";
import { Event } from "@dxos/async";
import { live } from "@dxos/live-object";
import { log as log2 } from "@dxos/log";
var __dxlog_file2 = "/__w/dxos/dxos/packages/sdk/app-framework/src/core/manager.ts";
var isPromise = (value) => {
  return value !== null && typeof value === "object" && "then" in value;
};
var PluginManager = class {
  constructor({ pluginLoader, plugins = [], core = plugins.map(({ meta }) => meta.id), enabled = [], registry }) {
    this.activation = new Event();
    this._capabilities = /* @__PURE__ */ new Map();
    this.registry = registry ?? Registry.make();
    this.context = new PluginContext({
      registry: this.registry,
      activate: (event) => this._activate(event),
      reset: (id) => this._reset(id)
    });
    this._pluginLoader = pluginLoader;
    this._state = live({
      plugins,
      core,
      enabled,
      modules: [],
      active: [],
      pendingReset: [],
      eventsFired: []
    });
    plugins.forEach((plugin) => this._addPlugin(plugin));
    core.forEach((id) => this.enable(id));
    enabled.forEach((id) => this.enable(id));
  }
  /**
  * Plugins that are currently registered.
  *
  * @reactive
  */
  get plugins() {
    return this._state.plugins;
  }
  /**
  * Ids of plugins that are core and cannot be removed.
  *
  * @reactive
  */
  get core() {
    return this._state.core;
  }
  /**
  * Ids of plugins that are currently enabled.
  *
  * @reactive
  */
  get enabled() {
    return this._state.enabled;
  }
  /**
  * Modules of plugins which are currently enabled.
  *
  * @reactive
  */
  get modules() {
    return this._state.modules;
  }
  /**
  * Ids of modules which are currently active.
  *
  * @reactive
  */
  get active() {
    return this._state.active;
  }
  /**
  * Ids of events which have been fired.
  *
  * @reactive
  */
  get eventsFired() {
    return this._state.eventsFired;
  }
  /**
  * Ids of modules which are pending reset.
  *
  * @reactive
  */
  get pendingReset() {
    return this._state.pendingReset;
  }
  /**
  * Adds a plugin to the manager via the plugin loader.
  * @param id The id of the plugin.
  */
  async add(id) {
    return untracked(async () => {
      log2("add plugin", {
        id
      }, {
        F: __dxlog_file2,
        L: 154,
        S: this,
        C: (f, a) => f(...a)
      });
      const plugin = await this._pluginLoader(id);
      this._addPlugin(plugin);
      return this.enable(id);
    });
  }
  /**
  * Enables a plugin.
  * @param id The id of the plugin.
  */
  enable(id) {
    return untracked(async () => {
      log2("enable plugin", {
        id
      }, {
        F: __dxlog_file2,
        L: 167,
        S: this,
        C: (f, a) => f(...a)
      });
      const plugin = this._getPlugin(id);
      if (!plugin) {
        return false;
      }
      if (!this._state.enabled.includes(id)) {
        this._state.enabled.push(id);
      }
      plugin.modules.forEach((module) => {
        this._addModule(module);
        this._setPendingResetByModule(module);
      });
      log2("pending reset", {
        events: [
          ...this.pendingReset
        ]
      }, {
        F: __dxlog_file2,
        L: 182,
        S: this,
        C: (f, a) => f(...a)
      });
      await Effect2.runPromise(Effect2.all(this.pendingReset.map((event) => this._activate(event)), {
        concurrency: "unbounded"
      }));
      return true;
    });
  }
  /**
  * Removes a plugin from the manager.
  * @param id The id of the plugin.
  */
  remove(id) {
    return untracked(() => {
      log2("remove plugin", {
        id
      }, {
        F: __dxlog_file2,
        L: 200,
        S: this,
        C: (f, a) => f(...a)
      });
      const result = this.disable(id);
      if (!result) {
        return false;
      }
      this._removePlugin(id);
      return true;
    });
  }
  /**
  * Disables a plugin.
  * @param id The id of the plugin.
  */
  disable(id) {
    return untracked(async () => {
      log2("disable plugin", {
        id
      }, {
        F: __dxlog_file2,
        L: 217,
        S: this,
        C: (f, a) => f(...a)
      });
      if (this._state.core.includes(id)) {
        return false;
      }
      const plugin = this._getPlugin(id);
      if (!plugin) {
        return false;
      }
      const enabledIndex = this._state.enabled.findIndex((enabled) => enabled === id);
      if (enabledIndex !== -1) {
        this._state.enabled.splice(enabledIndex, 1);
        await Effect2.runPromise(this._deactivate(id));
        plugin.modules.forEach((module) => {
          this._removeModule(module.id);
        });
      }
      return true;
    });
  }
  /**
  * Activates plugins based on the activation event.
  * @param event The activation event.
  * @returns Whether the activation was successful.
  */
  activate(event) {
    return untracked(() => Effect2.runPromise(this._activate(event)));
  }
  /**
  * Deactivates all of the modules for a plugin.
  * @param id The id of the plugin.
  * @returns Whether the deactivation was successful.
  */
  deactivate(id) {
    return untracked(() => Effect2.runPromise(this._deactivate(id)));
  }
  /**
  * Re-activates the modules that were activated by the event.
  * @param event The activation event.
  * @returns Whether the reset was successful.
  */
  reset(event) {
    return untracked(() => Effect2.runPromise(this._reset(event)));
  }
  _addPlugin(plugin) {
    untracked(() => {
      log2("add plugin", {
        id: plugin.meta.id
      }, {
        F: __dxlog_file2,
        L: 270,
        S: this,
        C: (f, a) => f(...a)
      });
      if (!this._state.plugins.includes(plugin)) {
        this._state.plugins.push(plugin);
      }
    });
  }
  _removePlugin(id) {
    untracked(() => {
      log2("remove plugin", {
        id
      }, {
        F: __dxlog_file2,
        L: 279,
        S: this,
        C: (f, a) => f(...a)
      });
      const pluginIndex = this._state.plugins.findIndex((plugin) => plugin.meta.id === id);
      if (pluginIndex !== -1) {
        this._state.plugins.splice(pluginIndex, 1);
      }
    });
  }
  _addModule(module) {
    untracked(() => {
      log2("add module", {
        id: module.id
      }, {
        F: __dxlog_file2,
        L: 289,
        S: this,
        C: (f, a) => f(...a)
      });
      if (!this._state.modules.includes(module)) {
        this._state.modules.push(module);
      }
    });
  }
  _removeModule(id) {
    untracked(() => {
      log2("remove module", {
        id
      }, {
        F: __dxlog_file2,
        L: 298,
        S: this,
        C: (f, a) => f(...a)
      });
      const moduleIndex = this._state.modules.findIndex((module) => module.id === id);
      if (moduleIndex !== -1) {
        this._state.modules.splice(moduleIndex, 1);
      }
    });
  }
  _getPlugin(id) {
    return this._state.plugins.find((plugin) => plugin.meta.id === id);
  }
  _getActiveModules() {
    return this._state.modules.filter((module) => this._state.active.includes(module.id));
  }
  _getInactiveModules() {
    return this._state.modules.filter((module) => !this._state.active.includes(module.id));
  }
  _getActiveModulesByEvent(key) {
    return this._getActiveModules().filter((module) => getEvents(module.activatesOn).map(eventKey).includes(key));
  }
  _getInactiveModulesByEvent(key) {
    return this._getInactiveModules().filter((module) => getEvents(module.activatesOn).map(eventKey).includes(key));
  }
  _setPendingResetByModule(module) {
    return untracked(() => {
      const activationEvents = getEvents(module.activatesOn).map(eventKey).filter((key) => this._state.eventsFired.includes(key));
      const pendingReset = Array.from(new Set(activationEvents)).filter((event) => !this._state.pendingReset.includes(event));
      if (pendingReset.length > 0) {
        log2("pending reset", {
          events: pendingReset
        }, {
          F: __dxlog_file2,
          L: 336,
          S: this,
          C: (f, a) => f(...a)
        });
        this._state.pendingReset.push(...pendingReset);
      }
    });
  }
  /**
  * @internal
  */
  // TODO(wittjosiah): Improve error typing.
  _activate(event) {
    return Effect2.gen(this, function* () {
      const key = typeof event === "string" ? event : eventKey(event);
      log2("activating", {
        key
      }, {
        F: __dxlog_file2,
        L: 349,
        S: this,
        C: (f, a) => f(...a)
      });
      const pendingIndex = this._state.pendingReset.findIndex((event2) => event2 === key);
      if (pendingIndex !== -1) {
        this._state.pendingReset.splice(pendingIndex, 1);
      }
      const modules = this._getInactiveModulesByEvent(key).filter((module) => {
        const allOf2 = isAllOf(module.activatesOn);
        if (!allOf2) {
          return true;
        }
        const events = module.activatesOn.events.filter((event2) => eventKey(event2) !== key);
        return events.every((event2) => this._state.eventsFired.includes(eventKey(event2)));
      });
      if (modules.length === 0) {
        log2("no modules to activate", {
          key
        }, {
          F: __dxlog_file2,
          L: 365,
          S: this,
          C: (f, a) => f(...a)
        });
        if (!this._state.eventsFired.includes(key)) {
          this._state.eventsFired.push(key);
        }
        return false;
      }
      log2("activating modules", {
        key,
        modules: modules.map((module) => module.id)
      }, {
        F: __dxlog_file2,
        L: 372,
        S: this,
        C: (f, a) => f(...a)
      });
      this.activation.emit({
        event: key,
        state: "activating"
      });
      const getCapabilities = yield* Effect2.all(modules.map(({ activate }) => Effect2.tryPromise({
        try: async () => activate(this.context),
        catch: (error) => error
      })), {
        concurrency: "unbounded"
      });
      const result = yield* pipe(
        modules,
        A.zip(getCapabilities),
        A.map(([module, getCapabilities2]) => this._activateModule(module, getCapabilities2)),
        // TODO(wittjosiah): This currently can't be run in parallel.
        //   Running this with concurrency causes races with `allOf` activation events.
        Effect2.all,
        Effect2.either
      );
      if (Either.isLeft(result)) {
        this.activation.emit({
          event: key,
          state: "error",
          error: result.left
        });
        yield* Effect2.fail(result.left);
      }
      if (!this._state.eventsFired.includes(key)) {
        this._state.eventsFired.push(key);
      }
      this.activation.emit({
        event: key,
        state: "activated"
      });
      log2("activated", {
        key
      }, {
        F: __dxlog_file2,
        L: 406,
        S: this,
        C: (f, a) => f(...a)
      });
      return true;
    });
  }
  _activateModule(module, getCapabilities) {
    return Effect2.gen(this, function* () {
      yield* Effect2.all(module.activatesBefore?.map((event) => this._activate(event)) ?? [], {
        concurrency: "unbounded"
      });
      log2("activating module...", {
        module: module.id
      }, {
        F: __dxlog_file2,
        L: 421,
        S: this,
        C: (f, a) => f(...a)
      });
      const maybeCapabilities = typeof getCapabilities === "function" ? getCapabilities() : getCapabilities;
      const resolvedCapabilities = yield* Match.value(maybeCapabilities).pipe(
        // TODO(wittjosiah): Activate with an effect?
        // Match.when(Effect.isEffect, (effect) => effect),
        Match.when(isPromise, (promise) => Effect2.tryPromise({
          try: () => promise,
          catch: (error) => error
        })),
        Match.orElse((program) => Effect2.succeed(program))
      );
      const capabilities = Match.value(resolvedCapabilities).pipe(Match.when(Array.isArray, (array) => array), Match.orElse((value) => [
        value
      ]));
      capabilities.forEach((capability) => {
        this.context.contributeCapability({
          module: module.id,
          ...capability
        });
      });
      this._state.active.push(module.id);
      this._capabilities.set(module.id, capabilities);
      log2("activated module", {
        module: module.id
      }, {
        F: __dxlog_file2,
        L: 444,
        S: this,
        C: (f, a) => f(...a)
      });
      yield* Effect2.all(module.activatesAfter?.map((event) => this._activate(event)) ?? [], {
        concurrency: "unbounded"
      });
    });
  }
  _deactivate(id) {
    return Effect2.gen(this, function* () {
      const plugin = this._getPlugin(id);
      if (!plugin) {
        return false;
      }
      const modules = plugin.modules;
      const results = yield* Effect2.all(modules.map((module) => this._deactivateModule(module)), {
        concurrency: "unbounded"
      });
      return results.every((result) => result);
    });
  }
  _deactivateModule(module) {
    return Effect2.gen(this, function* () {
      const id = module.id;
      log2("deactivating", {
        id
      }, {
        F: __dxlog_file2,
        L: 471,
        S: this,
        C: (f, a) => f(...a)
      });
      const capabilities = this._capabilities.get(id);
      if (capabilities) {
        for (const capability of capabilities) {
          this.context.removeCapability(capability.interface, capability.implementation);
          const program = capability.deactivate?.();
          yield* Match.value(program).pipe(Match.when(Effect2.isEffect, (effect) => effect), Match.when(isPromise, (promise) => Effect2.tryPromise({
            try: () => promise,
            catch: (error) => error
          })), Match.orElse((program2) => Effect2.succeed(program2)));
        }
        this._capabilities.delete(id);
      }
      const activeIndex = this._state.active.findIndex((event) => event === id);
      if (activeIndex !== -1) {
        this._state.active.splice(activeIndex, 1);
      }
      log2("deactivated", {
        id
      }, {
        F: __dxlog_file2,
        L: 497,
        S: this,
        C: (f, a) => f(...a)
      });
      return true;
    });
  }
  _reset(event) {
    return Effect2.gen(this, function* () {
      const key = typeof event === "string" ? event : eventKey(event);
      log2("reset", {
        key
      }, {
        F: __dxlog_file2,
        L: 505,
        S: this,
        C: (f, a) => f(...a)
      });
      const modules = this._getActiveModulesByEvent(key);
      const results = yield* Effect2.all(modules.map((module) => this._deactivateModule(module)), {
        concurrency: "unbounded"
      });
      if (results.every((result) => result)) {
        return yield* this._activate(key);
      } else {
        return false;
      }
    });
  }
};

// src/core/plugin.ts
var PluginModule = class {
  constructor(options) {
    this.id = options.id;
    this.activatesOn = options.activatesOn;
    this.activatesBefore = options.activatesBefore;
    this.activatesAfter = options.activatesAfter;
    this.activate = options.activate;
  }
};
var defineModule = (options) => new PluginModule(options);
var Plugin = class {
  constructor(meta, modules) {
    this.meta = meta;
    this.modules = modules;
  }
};
var definePlugin = (meta, modules) => {
  return new Plugin(meta, modules);
};

// src/common/capabilities.ts
(function(Capabilities2) {
  Capabilities2.Null = defineCapability("dxos.org/app-framework/capability/null");
  Capabilities2.PluginManager = defineCapability("dxos.org/app-framework/capability/plugin-manager");
  Capabilities2.RxRegistry = defineCapability("dxos.org/app-framework/capability/rx-registry");
  Capabilities2.ReactContext = defineCapability("dxos.org/app-framework/capability/react-context");
  Capabilities2.ReactRoot = defineCapability("dxos.org/app-framework/capability/react-root");
  Capabilities2.ReactSurface = defineCapability("dxos.org/app-framework/common/react-surface");
  Capabilities2.IntentResolver = defineCapability("dxos.org/app-framework/capability/intent-resolver");
  Capabilities2.IntentDispatcher = defineCapability("dxos.org/app-framework/capability/intent-dispatcher");
  Capabilities2.Layout = defineCapability("dxos.org/app-framework/capability/layout");
  Capabilities2.Translations = defineCapability("dxos.org/app-framework/capability/translations");
  Capabilities2.AppGraph = defineCapability("dxos.org/app-framework/capability/app-graph");
  Capabilities2.AppGraphBuilder = defineCapability("dxos.org/app-framework/capability/app-graph-builder");
  Capabilities2.AppGraphSerializer = defineCapability("dxos.org/app-framework/capability/app-graph-serializer");
  Capabilities2.SettingsStore = defineCapability("dxos.org/app-framework/capability/settings-store");
  Capabilities2.Settings = defineCapability("dxos.org/app-framework/capability/settings");
  Capabilities2.Metadata = defineCapability("dxos.org/app-framework/capability/metadata");
  Capabilities2.Tools = defineCapability("dxos.org/app-framework/capability/tools");
  Capabilities2.ArtifactDefinition = defineCapability("dxos.org/app-framework/capability/artifact-definition");
  Capabilities2.Functions = defineCapability("dxos.org/app-framework/capability/functions");
  Capabilities2.FileUploader = defineCapability("dxos.org/app-framework/capability/file-uploader");
  Capabilities2.AnchorSort = defineCapability("dxos.org/app-framework/capability/anchor-sort");
})(Capabilities || (Capabilities = {}));
var Capabilities;

// src/common/collaboration.ts
import { Schema as Schema3 } from "effect";
import { Expando, Ref } from "@dxos/echo-schema";
(function(CollaborationActions2) {
  class InsertContent extends Schema3.TaggedClass()("assistant/intent-content", {
    input: Schema3.Struct({
      target: Expando,
      object: Ref(Expando),
      at: Schema3.optional(Schema3.String),
      label: Schema3.String.pipe(Schema3.optional)
    }).annotations({
      description: "Enables plugins to inject content blocks or references into a related entity."
    }),
    output: Schema3.Void
  }) {
  }
  CollaborationActions2.InsertContent = InsertContent;
})(CollaborationActions || (CollaborationActions = {}));
var CollaborationActions;

// src/common/events.ts
(function(Events2) {
  Events2.Startup = defineEvent("dxos.org/app-framework/event/startup");
  Events2.SetupReactSurface = defineEvent("dxos.org/app-framework/event/setup-react-surface");
  Events2.SetupMetadata = defineEvent("dxos.org/app-framework/event/setup-metadata");
  Events2.SetupIntentResolver = defineEvent("dxos.org/app-framework/event/setup-intent-resolver");
  Events2.SetupSettings = defineEvent("dxos.org/app-framework/event/setup-settings");
  Events2.SetupAppGraph = defineEvent("dxos.org/app-framework/event/setup-graph");
  Events2.SetupTranslations = defineEvent("dxos.org/app-framework/event/setup-translations");
  Events2.SetupArtifactDefinition = defineEvent("dxos.org/app-framework/event/setup-artifact-definition");
  Events2.DispatcherReady = defineEvent("dxos.org/app-framework/event/dispatcher-ready");
  Events2.SettingsReady = defineEvent("dxos.org/app-framework/event/settings-ready");
  Events2.AppGraphReady = defineEvent("dxos.org/app-framework/event/graph-ready");
  Events2.createStateEvent = (specifier) => defineEvent("dxos.org/app-framework/event/state", specifier);
  Events2.LayoutReady = Events2.createStateEvent(Capabilities.Layout.identifier);
})(Events || (Events = {}));
var Events;

// src/common/file.ts
import { Schema as Schema4 } from "effect";
var defaultFileTypes = {
  images: [
    "png",
    "jpg",
    "jpeg",
    "gif"
  ],
  media: [
    "mp3",
    "mp4",
    "mov",
    "avi"
  ],
  text: [
    "pdf",
    "txt",
    "md"
  ]
};
var FileInfoSchema = Schema4.Struct({
  name: Schema4.String,
  type: Schema4.String,
  url: Schema4.optional(Schema4.String),
  cid: Schema4.optional(Schema4.String)
});

// src/common/layout.ts
import { Schema as Schema5 } from "effect";

// src/plugin-intent/IntentPlugin.ts
var IntentPlugin = () => definePlugin({
  id: INTENT_PLUGIN,
  name: "Intent"
}, [
  defineModule({
    id: `${INTENT_PLUGIN}/module/dispatcher`,
    // TODO(wittjosiah): This will mean that startup needs to be reset when intents are added or removed.
    //   This is fine for now because it's how it worked prior to capabilities api anyways.
    //   In the future, the intent dispatcher should be able to be reset without resetting the entire app.
    activatesOn: Events.Startup,
    activatesAfter: [
      Events.DispatcherReady
    ],
    activate: lazy(() => import("./intent-dispatcher-LSYQZSEB.mjs"))
  })
]);

// src/common/layout.ts
var LAYOUT_PLUGIN = "dxos.org/plugin/layout";
var LAYOUT_ACTION = `${LAYOUT_PLUGIN}/action`;
(function(LayoutAction2) {
  LayoutAction2.UPDATE_LAYOUT = `${LAYOUT_ACTION}/update-layout`;
  class UpdateLayout extends Schema5.TaggedClass()(LayoutAction2.UPDATE_LAYOUT, {
    input: Schema5.Struct({
      part: Schema5.String.annotations({
        description: "The part of the layout to mutate."
      }),
      subject: Schema5.optional(Schema5.Any.annotations({
        description: "The subject of the layout update."
      })),
      options: Schema5.optional(Schema5.Record({
        key: Schema5.String,
        value: Schema5.Any
      }).annotations({
        description: "Additional options for the layout action."
      }))
    }),
    output: Schema5.Void
  }) {
  }
  LayoutAction2.UpdateLayout = UpdateLayout;
  class SetLayoutMode extends Schema5.TaggedClass()(LayoutAction2.UPDATE_LAYOUT, {
    input: Schema5.Struct({
      part: Schema5.Literal("mode").annotations({
        description: "Setting the layout mode."
      }),
      subject: Schema5.optional(Schema5.String.annotations({
        description: "Item which is the subject of the new layout mode."
      })),
      options: Schema5.Union(Schema5.Struct({
        mode: Schema5.String.annotations({
          description: "The new layout mode."
        })
      }), Schema5.Struct({
        revert: Schema5.Boolean.annotations({
          description: "Revert to the previous layout mode."
        })
      }))
    }),
    output: Schema5.Void
  }) {
  }
  LayoutAction2.SetLayoutMode = SetLayoutMode;
  class UpdateSidebar extends Schema5.TaggedClass()(LayoutAction2.UPDATE_LAYOUT, {
    input: Schema5.Struct({
      part: Schema5.Literal("sidebar").annotations({
        description: "Updating the sidebar."
      }),
      subject: Schema5.optional(Schema5.String.annotations({
        description: "URI of the component to display in the sidebar."
      })),
      options: Schema5.optional(Schema5.Struct({
        state: Schema5.Literal("closed", "collapsed", "expanded").annotations({
          description: "Whether the sidebar is closed, collapsed, or expanded."
        })
      }))
    }),
    output: Schema5.Void
  }) {
  }
  LayoutAction2.UpdateSidebar = UpdateSidebar;
  class UpdateComplementary extends Schema5.TaggedClass()(LayoutAction2.UPDATE_LAYOUT, {
    input: Schema5.Struct({
      part: Schema5.Literal("complementary").annotations({
        description: "Updating the complementary sidebar."
      }),
      subject: Schema5.optional(Schema5.String.annotations({
        description: "URI of the component to display in the complementary area."
      })),
      options: Schema5.optional(Schema5.Struct({
        state: Schema5.Literal("closed", "collapsed", "expanded").annotations({
          description: "Whether the complementary sidebar is closed, collapsed, or expanded."
        })
      }))
    }),
    output: Schema5.Void
  }) {
  }
  LayoutAction2.UpdateComplementary = UpdateComplementary;
  class UpdateDialog extends Schema5.TaggedClass()(LayoutAction2.UPDATE_LAYOUT, {
    input: Schema5.Struct({
      part: Schema5.Literal("dialog").annotations({
        description: "Updating the dialog."
      }),
      subject: Schema5.optional(Schema5.String.annotations({
        description: "URI of the component to display in the dialog."
      })),
      options: Schema5.Struct({
        state: Schema5.optional(Schema5.Boolean.annotations({
          description: "Whether the dialog is open or closed."
        })),
        type: Schema5.optional(Schema5.Literal("default", "alert").annotations({
          description: "The type of dialog."
        })),
        blockAlign: Schema5.optional(Schema5.Literal("start", "center", "end").annotations({
          description: "The alignment of the dialog."
        })),
        overlayClasses: Schema5.optional(Schema5.String.annotations({
          description: "Additional classes for the dialog overlay."
        })),
        overlayStyle: Schema5.optional(Schema5.Record({
          key: Schema5.String,
          value: Schema5.Any
        }).annotations({
          description: "Additional styles for the dialog overlay."
        })),
        props: Schema5.optional(Schema5.Record({
          key: Schema5.String,
          value: Schema5.Any
        }).annotations({
          description: "Additional props for the dialog."
        }))
      })
    }),
    output: Schema5.Void
  }) {
  }
  LayoutAction2.UpdateDialog = UpdateDialog;
  class UpdatePopover extends Schema5.TaggedClass()(LayoutAction2.UPDATE_LAYOUT, {
    input: Schema5.Struct({
      part: Schema5.Literal("popover").annotations({
        description: "Updating the popover."
      }),
      subject: Schema5.optional(Schema5.Any.annotations({
        description: "URI of the component to display in the popover or data to pass to the popover."
      })),
      options: Schema5.Struct({
        side: Schema5.optional(Schema5.Literal("top", "right", "bottom", "left").annotations({
          description: "The side of the anchor."
        })),
        state: Schema5.optional(Schema5.Boolean.annotations({
          description: "Whether the popover is open or closed."
        })),
        props: Schema5.optional(Schema5.Record({
          key: Schema5.String,
          value: Schema5.Any
        }).annotations({
          description: "Additional props for the popover."
        }))
      }).pipe(Schema5.extend(Schema5.Union(Schema5.Struct({
        variant: Schema5.Literal("virtual"),
        anchor: Schema5.Any.annotations({
          description: "The DOM element to anchor the popover to."
        })
      }), Schema5.Struct({
        variant: Schema5.optional(Schema5.Literal("react")),
        anchorId: Schema5.String.annotations({
          description: "An id that can be used to determine whether to render the anchor subcomponent."
        })
      }))))
    }),
    output: Schema5.Void
  }) {
  }
  LayoutAction2.UpdatePopover = UpdatePopover;
  LayoutAction2.Toast = Schema5.Struct({
    id: Schema5.String.annotations({
      description: "The id of the toast."
    }),
    title: Schema5.optional(Label.annotations({
      description: "The title of the toast."
    })),
    description: Schema5.optional(Label.annotations({
      description: "The description of the toast."
    })),
    icon: Schema5.optional(Schema5.String.annotations({
      description: "The icon of the toast."
    })),
    duration: Schema5.optional(Schema5.Number.annotations({
      description: "The duration of the toast."
    })),
    closeLabel: Schema5.optional(Label.annotations({
      description: "The label of the close button."
    })),
    actionLabel: Schema5.optional(Label.annotations({
      description: "The label of the action button."
    })),
    actionAlt: Schema5.optional(Label.annotations({
      description: "The alt text of the action button."
    })),
    onAction: Schema5.optional(Schema5.Any.annotations({
      description: "The action to perform when the action button is clicked."
    }))
  });
  class AddToast extends Schema5.TaggedClass()(LayoutAction2.UPDATE_LAYOUT, {
    input: Schema5.Struct({
      part: Schema5.Literal("toast").annotations({
        description: "Adding a toast."
      }),
      subject: LayoutAction2.Toast.annotations({
        description: "The toast to add."
      })
    }),
    output: Schema5.Void
  }) {
  }
  LayoutAction2.AddToast = AddToast;
  class SwitchWorkspace extends Schema5.TaggedClass()(LayoutAction2.UPDATE_LAYOUT, {
    input: Schema5.Struct({
      part: Schema5.Literal("workspace").annotations({
        description: "Switching the workspace."
      }),
      subject: Schema5.String.annotations({
        description: "The id of the workspace to switch to."
      })
    }),
    output: Schema5.Void
  }) {
  }
  LayoutAction2.SwitchWorkspace = SwitchWorkspace;
  class RevertWorkspace extends Schema5.TaggedClass()(LayoutAction2.UPDATE_LAYOUT, {
    input: Schema5.Struct({
      part: Schema5.Literal("workspace").annotations({
        description: "Switching the workspace."
      }),
      options: Schema5.Struct({
        revert: Schema5.Literal(true).annotations({
          description: "Revert to the previous workspace."
        })
      })
    }),
    output: Schema5.Void
  }) {
  }
  LayoutAction2.RevertWorkspace = RevertWorkspace;
  class Open extends Schema5.TaggedClass()(LayoutAction2.UPDATE_LAYOUT, {
    input: Schema5.Struct({
      part: Schema5.Literal("main").annotations({
        description: "Opening an item in the main content area."
      }),
      subject: Schema5.Array(Schema5.String.annotations({
        description: "Ids of the items to open."
      })),
      options: Schema5.optional(Schema5.Struct({
        state: Schema5.optional(Schema5.Literal(true).annotations({
          description: "The items are being added."
        })),
        variant: Schema5.optional(Schema5.String.annotations({
          description: "The variant of the item to open."
        })),
        key: Schema5.optional(Schema5.String.annotations({
          description: "If provided, will replace item with a matching key (id prefix)."
        })),
        workspace: Schema5.optional(Schema5.String.annotations({
          description: "The workspace to open the items in."
        })),
        scrollIntoView: Schema5.optional(Schema5.Boolean.annotations({
          description: "Scroll the items into view."
        })),
        pivotId: Schema5.optional(Schema5.String.annotations({
          description: "The id of the item to place new items next to."
        })),
        positioning: Schema5.optional(Schema5.Union(Schema5.Literal("start").annotations({
          description: "The items are being added before the pivot item."
        }), Schema5.Literal("end").annotations({
          description: "The items are being added after the pivot item."
        })))
      }))
    }),
    output: Schema5.Void
  }) {
  }
  LayoutAction2.Open = Open;
  class Set2 extends Schema5.TaggedClass()(LayoutAction2.UPDATE_LAYOUT, {
    input: Schema5.Struct({
      part: Schema5.Literal("main").annotations({
        description: "Setting items in the main content area."
      }),
      subject: Schema5.Array(Schema5.String.annotations({
        description: "Ids of the items to set."
      })),
      options: Schema5.Struct({
        override: Schema5.Literal(true).annotations({
          description: "Override the current items in the main content area."
        })
      })
    }),
    output: Schema5.Void
  }) {
  }
  LayoutAction2.Set = Set2;
  class Close extends Schema5.TaggedClass()(LayoutAction2.UPDATE_LAYOUT, {
    input: Schema5.Struct({
      part: Schema5.Literal("main").annotations({
        description: "Closing items in the main content area."
      }),
      subject: Schema5.Array(Schema5.String.annotations({
        description: "Ids of the items to close."
      })),
      options: Schema5.Struct({
        state: Schema5.Literal(false).annotations({
          description: "The items are being removed."
        })
      })
    }),
    output: Schema5.Void
  }) {
  }
  LayoutAction2.Close = Close;
  class ScrollIntoView extends Schema5.TaggedClass()(LayoutAction2.UPDATE_LAYOUT, {
    input: Schema5.Struct({
      part: Schema5.Literal("current").annotations({
        description: "Setting the current item"
      }),
      subject: Schema5.optional(Schema5.String.annotations({
        description: "The id of the item to set as current."
      })),
      options: Schema5.optional(Schema5.Record({
        key: Schema5.String,
        value: Schema5.Any
      }).annotations({
        description: "Additional options for the scroll into view."
      }))
    }),
    output: Schema5.Void
  }) {
  }
  LayoutAction2.ScrollIntoView = ScrollIntoView;
  class Expose extends Schema5.TaggedClass()(LayoutAction2.UPDATE_LAYOUT, {
    input: Schema5.Struct({
      part: Schema5.Literal("navigation").annotations({
        description: "Exposing an item in the navigation area."
      }),
      subject: Schema5.String.annotations({
        description: "The id of the item to expose."
      })
    }),
    output: Schema5.Void
  }) {
  }
  LayoutAction2.Expose = Expose;
})(LayoutAction || (LayoutAction = {}));
var LayoutAction;

// src/common/surface.ts
var createSurface = (definition) => definition;

// src/common/translations.ts
import { Schema as Schema6 } from "effect";
var ResourceKey = Schema6.Union(Schema6.String, Schema6.Record({
  key: Schema6.String,
  value: Schema6.Any
}));
var ResourceLanguage = Schema6.Record({
  key: Schema6.String,
  value: ResourceKey
});
var Resource = Schema6.Record({
  key: Schema6.String,
  value: ResourceLanguage
});

// src/plugin-intent/intent-dispatcher.ts
var __dxlog_file3 = "/__w/dxos/dxos/packages/sdk/app-framework/src/plugin-intent/intent-dispatcher.ts";
var EXECUTION_LIMIT = 100;
var HISTORY_LIMIT = 100;
var createResolver = (resolver) => resolver;
var isUndoable = (historyEntry) => historyEntry.length > 0 && historyEntry.every(({ undoable }) => !!undoable);
var createDispatcher = (getResolvers, { executionLimit = EXECUTION_LIMIT, historyLimit = HISTORY_LIMIT } = {}) => {
  const historyRef = Effect3.runSync(Ref2.make([]));
  const handleIntent = (intent) => Effect3.gen(function* () {
    const candidates = getResolvers().filter((resolver) => resolver.intent._tag === intent.id).filter((resolver) => !resolver.filter || resolver.filter(intent.data)).toSorted(byPosition);
    if (candidates.length === 0) {
      yield* Effect3.fail(new NoResolversError(intent.id));
    }
    const effect = candidates[0].resolve(intent.data, intent.undo ?? false);
    const result = Effect3.isEffect(effect) ? yield* effect : yield* Effect3.promise(async () => effect);
    return {
      _intent: intent,
      ...result
    };
  });
  const dispatch = (intentChain, depth = 0) => {
    return Effect3.gen(function* () {
      if (depth > executionLimit) {
        yield* Effect3.fail(new CycleDetectedError());
      }
      const resultsRef = yield* Ref2.make([]);
      for (const intent of intentChain.all) {
        const { data: prev } = (yield* resultsRef.get)[0] ?? {};
        const result2 = yield* handleIntent({
          ...intent,
          data: {
            ...intent.data,
            ...prev
          }
        });
        yield* Ref2.update(resultsRef, (results2) => [
          result2,
          ...results2
        ]);
        if (result2.intents) {
          for (const intent2 of result2.intents) {
            yield* dispatch(intent2, depth + 1);
          }
        }
        if (result2.error) {
          yield* Effect3.fail(result2.error);
        }
      }
      const results = yield* resultsRef.get;
      const result = results[0];
      yield* Ref2.update(historyRef, (history) => {
        const next = [
          ...history,
          results
        ];
        if (next.length > historyLimit) {
          next.splice(0, next.length - historyLimit);
        }
        return next;
      });
      if (result.undoable && isUndoable(results)) {
        yield* pipe2(dispatch(createIntent(IntentAction.ShowUndo, {
          message: result.undoable.message
        })), Effect3.catchSome((err) => err instanceof NoResolversError ? Option.some(Effect3.succeed(void 0)) : Option.none()));
      }
      return result.data;
    });
  };
  const dispatchPromise = (intentChain) => {
    return Effect3.runPromise(dispatch(intentChain)).then((data) => ({
      data
    })).catch((error) => {
      log3.catch(error, void 0, {
        F: __dxlog_file3,
        L: 270,
        S: void 0,
        C: (f, a) => f(...a)
      });
      return {
        error
      };
    });
  };
  const undo = () => {
    return Effect3.gen(function* () {
      const history = yield* historyRef.get;
      const last = history.findLastIndex(isUndoable);
      const result = last !== -1 ? history[last] : void 0;
      if (result) {
        const all = result.map(({ _intent, undoable }) => {
          const data = _intent.data;
          const undoData = undoable?.data ?? {};
          return {
            ..._intent,
            data: {
              ...data,
              ...undoData
            },
            undo: true
          };
        });
        const intent = {
          first: all[0],
          last: all.at(-1),
          all
        };
        yield* Ref2.update(historyRef, (h) => h.filter((_, index) => index !== last));
        return yield* dispatch(intent);
      }
    });
  };
  const undoPromise = () => {
    return Effect3.runPromise(undo()).then((data) => ({
      data
    })).catch((error) => ({
      error
    }));
  };
  return {
    dispatch,
    dispatchPromise,
    undo,
    undoPromise
  };
};
var defaultEffect = () => Effect3.fail(new Error("Intent runtime not ready"));
var defaultPromise = () => Effect3.runPromise(defaultEffect());
var intent_dispatcher_default = (context) => {
  const state = live2({
    dispatch: defaultEffect,
    dispatchPromise: defaultPromise,
    undo: defaultEffect,
    undoPromise: defaultPromise
  });
  const { dispatch, dispatchPromise, undo, undoPromise } = createDispatcher(() => context.getCapabilities(Capabilities.IntentResolver).flat());
  const manager = context.getCapability(Capabilities.PluginManager);
  state.dispatch = (intentChain, depth) => {
    return Effect3.gen(function* () {
      yield* manager._activate(Events.SetupIntentResolver);
      return yield* dispatch(intentChain, depth);
    });
  };
  state.dispatchPromise = async (intentChain) => {
    await manager.activate(Events.SetupIntentResolver);
    return await dispatchPromise(intentChain);
  };
  state.undo = undo;
  state.undoPromise = undoPromise;
  return contributes(Capabilities.IntentDispatcher, state);
};

export {
  defineCapability,
  contributes,
  lazy,
  PluginContext,
  defineEvent,
  eventKey,
  oneOf,
  allOf,
  isOneOf,
  isAllOf,
  getEvents,
  PluginManager,
  PluginModule,
  defineModule,
  Plugin,
  definePlugin,
  Capabilities,
  CollaborationActions,
  Events,
  defaultFileTypes,
  FileInfoSchema,
  createIntent,
  chain,
  Label,
  INTENT_PLUGIN,
  INTENT_ACTION,
  IntentAction,
  createResolver,
  createDispatcher,
  intent_dispatcher_default,
  IntentPlugin,
  LAYOUT_PLUGIN,
  LAYOUT_ACTION,
  LayoutAction,
  createSurface,
  ResourceKey,
  ResourceLanguage,
  Resource
};
//# sourceMappingURL=chunk-FMN65HSW.mjs.map
