Skip to content

Commit 202f6d8

Browse files
committed
dashboard: add experimental features config section
1 parent cd3d702 commit 202f6d8

File tree

2 files changed

+124
-1
lines changed

2 files changed

+124
-1
lines changed

README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,18 @@ All durable states live in a local SQLite database. If the database can't be ope
385385

386386
---
387387

388+
## Star History
389+
390+
<a href="https://www.star-history.com/?repos=cortexkit%2Fopencode-magic-context&type=date&legend=bottom-right">
391+
<picture>
392+
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/chart?repos=cortexkit/opencode-magic-context&type=date&theme=dark&legend=top-left" />
393+
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/chart?repos=cortexkit/opencode-magic-context&type=date&legend=top-left" />
394+
<img alt="Star History Chart" src="https://api.star-history.com/chart?repos=cortexkit/opencode-magic-context&type=date&legend=top-left" />
395+
</picture>
396+
</a>
397+
398+
---
399+
388400
## Development
389401

390402
**Requirements:** [Bun](https://bun.sh) ≥ 1.0

packages/dashboard/src/components/ConfigEditor/ConfigEditor.tsx

Lines changed: 112 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,8 @@ const SECTION_ICONS: Record<string, string> = {
116116
"Thresholds": "⚡",
117117
"Tags & Cleanup": "🏷️",
118118
"Historian": "📜",
119-
120119
"Memory": "🧠",
120+
"Experimental": "🧪",
121121
};
122122

123123
// Fields that should use range sliders (percentage or threshold values)
@@ -849,6 +849,117 @@ function ConfigForm(props: {
849849
</div>
850850
);
851851
})()}
852+
853+
{/* Experimental Features */}
854+
{(() => {
855+
const exp = () => (getNestedValue(formData(), "experimental") as {
856+
compaction_markers?: boolean;
857+
user_memories?: { enabled?: boolean; promotion_threshold?: number };
858+
pin_key_files?: { enabled?: boolean; token_budget?: number; min_reads?: number };
859+
} | undefined) ?? {};
860+
861+
const compactionMarkers = () => exp().compaction_markers ?? false;
862+
const userMemEnabled = () => exp().user_memories?.enabled ?? false;
863+
const userMemThreshold = () => exp().user_memories?.promotion_threshold ?? 3;
864+
const pinEnabled = () => exp().pin_key_files?.enabled ?? false;
865+
const pinBudget = () => exp().pin_key_files?.token_budget ?? 10000;
866+
const pinMinReads = () => exp().pin_key_files?.min_reads ?? 4;
867+
868+
const updateExp = (path: string, value: unknown) => {
869+
const current = exp();
870+
if (path === "compaction_markers") {
871+
handleFieldChange("experimental", { ...current, compaction_markers: value });
872+
} else if (path.startsWith("user_memories.")) {
873+
const um = current.user_memories ?? { enabled: false, promotion_threshold: 3 };
874+
const field = path.split(".")[1];
875+
handleFieldChange("experimental", { ...current, user_memories: { ...um, [field]: value } });
876+
} else if (path.startsWith("pin_key_files.")) {
877+
const pk = current.pin_key_files ?? { enabled: false, token_budget: 10000, min_reads: 4 };
878+
const field = path.split(".")[1];
879+
handleFieldChange("experimental", { ...current, pin_key_files: { ...pk, [field]: value } });
880+
}
881+
};
882+
883+
return (
884+
<div class="config-card full-width">
885+
<div class="config-card-header">
886+
<span class="config-card-icon">🧪</span>
887+
<span class="config-card-title">Experimental</span>
888+
</div>
889+
<div class="config-card-two-col">
890+
{/* Left column: Compaction Markers + User Memories */}
891+
<div class="config-card-content">
892+
<div class="config-field">
893+
<label class="field-label">
894+
<span>Compaction Markers</span>
895+
<span class="field-hint">Inject boundary into OpenCode's DB so transform only processes the live tail</span>
896+
</label>
897+
<label class="toggle">
898+
<input type="checkbox" checked={compactionMarkers()} onChange={(e) => updateExp("compaction_markers", e.currentTarget.checked)} />
899+
<span class="toggle-slider" />
900+
<span class="toggle-label">{compactionMarkers() ? "Enabled" : "Disabled"}</span>
901+
</label>
902+
</div>
903+
904+
<div class="config-field" style={{ "margin-top": "16px" }}>
905+
<label class="field-label">
906+
<span>User Memories</span>
907+
<span class="field-hint">Extract behavioral observations from historian runs, promote recurring patterns to stable user memories. Requires dreamer.</span>
908+
</label>
909+
<label class="toggle">
910+
<input type="checkbox" checked={userMemEnabled()} onChange={(e) => updateExp("user_memories.enabled", e.currentTarget.checked)} />
911+
<span class="toggle-slider" />
912+
<span class="toggle-label">{userMemEnabled() ? "Enabled" : "Disabled"}</span>
913+
</label>
914+
</div>
915+
916+
<Show when={userMemEnabled()}>
917+
<div class="config-field" style={{ "margin-top": "8px", "padding-left": "12px" }}>
918+
<label class="field-label">
919+
<span>Promotion Threshold</span>
920+
<span class="field-hint">Minimum candidate observations before dreamer promotes to stable (2–20)</span>
921+
</label>
922+
<input type="number" class="field-input" min={2} max={20} value={userMemThreshold()} onInput={(e) => updateExp("user_memories.promotion_threshold", Number(e.currentTarget.value))} style={{ width: "80px" }} />
923+
</div>
924+
</Show>
925+
</div>
926+
927+
{/* Right column: Key File Pinning */}
928+
<div class="config-card-content">
929+
<div class="config-field">
930+
<label class="field-label">
931+
<span>Key File Pinning</span>
932+
<span class="field-hint">Pin frequently-read files into the system prompt so the agent doesn't need to re-read them after drops. Requires dreamer.</span>
933+
</label>
934+
<label class="toggle">
935+
<input type="checkbox" checked={pinEnabled()} onChange={(e) => updateExp("pin_key_files.enabled", e.currentTarget.checked)} />
936+
<span class="toggle-slider" />
937+
<span class="toggle-label">{pinEnabled() ? "Enabled" : "Disabled"}</span>
938+
</label>
939+
</div>
940+
941+
<Show when={pinEnabled()}>
942+
<div class="config-field" style={{ "margin-top": "8px", "padding-left": "12px" }}>
943+
<label class="field-label">
944+
<span>Token Budget</span>
945+
<span class="field-hint">Total tokens for all pinned key files (2,000–30,000)</span>
946+
</label>
947+
<input type="number" class="field-input" min={2000} max={30000} step={1000} value={pinBudget()} onInput={(e) => updateExp("pin_key_files.token_budget", Number(e.currentTarget.value))} style={{ width: "100px" }} />
948+
</div>
949+
950+
<div class="config-field" style={{ "margin-top": "8px", "padding-left": "12px" }}>
951+
<label class="field-label">
952+
<span>Min Reads</span>
953+
<span class="field-hint">Minimum full-read count before a file is eligible for pinning (2–20)</span>
954+
</label>
955+
<input type="number" class="field-input" min={2} max={20} value={pinMinReads()} onInput={(e) => updateExp("pin_key_files.min_reads", Number(e.currentTarget.value))} style={{ width: "80px" }} />
956+
</div>
957+
</Show>
958+
</div>
959+
</div>
960+
</div>
961+
);
962+
})()}
852963
</div>
853964
</Show>
854965
</div>

0 commit comments

Comments
 (0)