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
Files
views/general.ts4.7 KB
// The General section: appearance, runs, session import and the bug report.
// HTM whitespace is significant; keep these templates out of Prettier's HTML formatter.
import { html as htm } from "convergence";
import type { EffectViewContext } from "convergence/effect";
import type { SettingsPage } from "../controller.ts";
import { card, limit, section, segmented, setting, column } from "./layout.ts";
export function renderGeneral(ctx: EffectViewContext<object>, actions: SettingsPage["Service"]) {
const state = actions.state;
const s = state.settings;
// `renderGeneral` runs only once the settings have loaded.
if (!s) return htm`<empty>Loading…</empty>`;
return htm`
<div ...${column} gap="large" padding="small">
${section(
"Appearance",
null,
card([
setting({
title: "Color scheme",
description: "Follow the system, or keep one look.",
control: segmented(
"appearance",
s.appearance,
[
{ value: "system", label: "System" },
{ value: "light", label: "Light" },
{ value: "dark", label: "Dark" },
],
(value) => ctx.run(actions.changeAppearance(value)),
),
}),
setting({
title: "Theme",
description: "Presets, colours, type and density: the Themes plugin's settings.",
control: htm`<button id="open-themes" label="Edit themes" onClick=${() => ctx.run(actions.openSection("plugin:themes", "themes"))} />`,
}),
]),
)}
${section(
"Runs",
null,
card([
setting({
title: "Checkpoints",
description:
"Record the workspace before every prompt, so a message can be reverted together with the files it changed.",
control: htm`<switch id="checkpoints" label="" checked=${s.checkpoints} onChange=${(e: { value: boolean }) => ctx.run(actions.updateSettings({ checkpoints: e.value }))} />`,
}),
setting({
title: "Keep checkpoints for",
description: "Older checkpoints are deleted, and their messages can no longer be reverted.",
control: limit(
"checkpoint-days",
s.checkpointRetentionDays,
[7, 14, 30, 90],
(days) => `${days} days`,
"Forever",
(value) => ctx.run(actions.updateSettings({ checkpointRetentionDays: value })),
),
}),
setting({
title: "Checkpoint storage limit",
description: "Past this size the oldest checkpoints go first. Those from the last day are always kept.",
control: limit(
"checkpoint-size",
s.checkpointMaxMegabytes,
[512, 1024, 2048, 5120, 10240],
(mb) => (mb < 1024 ? `${mb} MB` : `${mb / 1024} GB`),
"No limit",
(value) => ctx.run(actions.updateSettings({ checkpointMaxMegabytes: value })),
),
}),
]),
)}
${section(
"Sessions",
null,
card([
setting({
title: "Import sessions",
description: "Bring existing sessions from enabled agents into a workspace.",
wide: true,
control: htm`
<div ...${column} gap="small" padding="small">
<select id="import-workspace" value=${state.importWorkspace ?? ""} placeholder="Add a workspace first"
options=${state.workspaces.map((w) => ({ value: w.id, label: w.name }))}
onChange=${(e: { value: string }) => {
state.importWorkspace = e.value;
ctx.update();
}} />
<button id="import-sessions" label="Import sessions" icon="inbox"
loading=${state.importing} disabled=${state.importing || !state.importWorkspace || !state.agents.some((agent) => agent.enabled)}
onClick=${() => ctx.run(actions.importSessions())} />
</div>`,
}),
]),
)}
${section(
"Help",
null,
card([
setting({
title: "Report a bug",
description:
"Tell us, or a plugin's publisher, what went wrong. You see everything that is sent before it goes.",
control: htm`<button id="report-bug" label="Report a bug…" icon="bug" variant="outline" onClick=${() => ctx.run(actions.reportBug())} />`,
}),
]),
)}
</div>`;
}Versions
| Version | Published | Plugin API | Size | Permissions | Status |
|---|---|---|---|---|---|
| 0.2.0latest | Oct 5, 2026 | >=2 <3 | 24.7 KB | 7 permissions | Listed |
No comments yet.