Official

settings

Built-in settings UI (JavaScript UI plugin).

The app opens the listing; nothing installs until an agent in your Plugins workspace has read the files and you enable the plugin. In a terminal: cvg install convergence/settings@0.2.0

Permissions in 0.2.0

  • Manage plugins plugins.manageOfficial onlyReloads and enables plugins. Only official plugins can have it.List, enable, disable and reload plugins, install updates, and quit to finish an update
  • Change app settings settings.writeHighChanges the app settings.Change the settings and the theme
  • Manage agents agents.manageHighEnables, disables and signs in agents, and changes their settings.Turn agents on and off, sign in to them and update them
  • Control chats chats.controlHighCreates chats, sends prompts and cancels runs.Import an agent's own sessions as chats
  • Read chats chats.readMediumReads your transcripts and chat lists.List the workspaces an agent's sessions can be imported into
  • Read app settings settings.readLowReads the app settings.Show the settings, and the tools and rules of every plugin
  • Show panels ui.slotsLowShows views in the listed parts of the window.Draw the settings pageSlots: center

Files

main.ts2.2 KB
// Register the settings page, then the convergence/settings service, then
// the host events that change what the page shows. The page loads the first
// time it is opened, not at activation.
import * as Effect from "effect/Effect";
import * as Stream from "effect/Stream";
import { Events, Services, Views, runPlugin } from "convergence/effect";
import type { HostEvents } from "convergence";
import { SettingsPage } from "./controller.ts";
import { Settings as SettingsService } from "./contract.ts";
import { renderSettings } from "./views/page.ts";

const program = Effect.gen(function* () {
  const page = yield* SettingsPage;
  const views = yield* Views;
  page.views.push(
    yield* views.slot("center", (ctx) => renderSettings(ctx, page), {
      on: [
        "app_state",
        "agents_changed",
        "plugins_changed",
        "updates_changed",
        "keybindings_changed",
        "plugin_settings_changed",
      ],
    }),
  );
  const services = yield* Services;
  yield* services.provide(SettingsService, {
    showShortcuts: ({ query }) => page.showShortcuts(query),
  });
  const events = yield* Events;
  // Every listener fires its effect as its own fork, as the original's
  // async listeners did; a failure is logged, not propagated.
  const follow = <E extends keyof HostEvents, R>(
    name: E,
    run: (event: HostEvents[E]) => Effect.Effect<void, unknown, R>,
  ) =>
    events.stream(name).pipe(
      Stream.runForEach((event) => Effect.forkScoped(run(event).pipe(Effect.ignore), { startImmediately: true })),
      Effect.ignore,
      Effect.forkScoped({ startImmediately: true }),
    );
  yield* follow("keybindings_changed", () => page.loadKeys());
  yield* follow("plugin_settings_changed", (event) =>
    page.state.sections[event.plugin] ? page.loadSection(event.plugin) : Effect.void,
  );
  yield* follow("agents_changed", () => page.load());
  yield* follow("plugins_changed", () => page.load());
  // A plugin enabled or turned off, or a grant given or taken back.
  yield* follow("access_changed", () => page.load());
  yield* follow("workspaces_changed", () => page.load());
  yield* follow("updates_changed", () => page.refreshUpdates());
});

export const activate = runPlugin(SettingsPage.layer, program);

Versions

VersionPublishedPlugin APISizePermissionsStatus
0.2.0latestOct 5, 2026>=2 <324.7 KB7 permissionsListed

Reviews and comments

0 threads · 0 reviews

No comments yet.