| author | |
| committer | |
| log | a19f01fc19d209d9962c4bb66372ed9e03e320a9 |
| tree | 64546d40239c1a6b180310bc02d7e8145be07581 |
| parent | 6ff537f03c4df500da7283c0566fe6f8feca709b |
| signature | Signed by PGP key B5690EEEBB952194 |
Co-authored-by: maria-rcks <254055478+maria-rcks@users.noreply.github.com>6 files changed, 45 insertions(+), 1 deletions(-)
apps/desktop/src/settings/DesktopClientSettings.test.ts+1| ... | ... | @@ -23,6 +23,7 @@ const clientSettings: ClientSettings = { |
| 23 | 23 | confirmThreadArchive: true, |
| 24 | 24 | confirmThreadDelete: false, |
| 25 | 25 | confirmThreadUnpin: false, |
| 26 | contextWindowMeterEnabled: false, | |
| 26 | 27 | dismissedProviderUpdateNotificationKeys: [], |
| 27 | 28 | diffIgnoreWhitespace: true, |
| 28 | 29 | environmentIdentificationMode: "artwork", |
apps/web/src/components/chat/ChatComposer.tsx+3-1| ... | ... | @@ -4339,7 +4339,9 @@ export const ChatComposer = memo(function ChatComposer(props: ChatComposerProps) |
| 4339 | 4339 | ) : null} |
| 4340 | 4340 | <ComposerFooterPrimaryActions |
| 4341 | 4341 | compact={isComposerPrimaryActionsCompact} |
| 4342 | activeContextWindow={activeContextWindow} | |
| 4342 | activeContextWindow={ | |
| 4343 | settings.contextWindowMeterEnabled ? activeContextWindow : null | |
| 4344 | } | |
| 4343 | 4345 | activeThreadModelDisplayName={activeThreadModelDisplayName} |
| 4344 | 4346 | pendingAction={pendingPrimaryAction} |
| 4345 | 4347 | isRunning={phase === "running"} |
apps/web/src/components/settings/SettingsPanels.tsx+19| ... | ... | @@ -522,6 +522,9 @@ export function useSettingsRestore(onRestored?: () => void) { |
| 522 | 522 | ...(settings.showSkillsInSlashMenu !== DEFAULT_UNIFIED_SETTINGS.showSkillsInSlashMenu |
| 523 | 523 | ? ["Show skills in slash menu"] |
| 524 | 524 | : []), |
| 525 | ...(settings.contextWindowMeterEnabled !== DEFAULT_UNIFIED_SETTINGS.contextWindowMeterEnabled | |
| 526 | ? ["Context window indicator"] | |
| 527 | : []), | |
| 525 | 528 | ...(settings.enableLegacyTokenStreaming !== |
| 526 | 529 | DEFAULT_UNIFIED_SETTINGS.enableLegacyTokenStreaming |
| 527 | 530 | ? ["Stream token by token"] |
| ... | ... | @@ -576,6 +579,7 @@ export function useSettingsRestore(onRestored?: () => void) { |
| 576 | 579 | settings.newWorktreesStartFromOrigin, |
| 577 | 580 | settings.diffIgnoreWhitespace, |
| 578 | 581 | settings.environmentIdentificationMode, |
| 582 | settings.contextWindowMeterEnabled, | |
| 579 | 583 | settings.fontFamilyCode, |
| 580 | 584 | settings.fontFamilyComposer, |
| 581 | 585 | settings.fontFamilySans, |
| ... | ... | @@ -668,6 +672,7 @@ export function useSettingsRestore(onRestored?: () => void) { |
| 668 | 672 | wordWrap: DEFAULT_UNIFIED_SETTINGS.wordWrap, |
| 669 | 673 | diffIgnoreWhitespace: DEFAULT_UNIFIED_SETTINGS.diffIgnoreWhitespace, |
| 670 | 674 | showSkillsInSlashMenu: DEFAULT_UNIFIED_SETTINGS.showSkillsInSlashMenu, |
| 675 | contextWindowMeterEnabled: DEFAULT_UNIFIED_SETTINGS.contextWindowMeterEnabled, | |
| 671 | 676 | environmentIdentificationMode: DEFAULT_UNIFIED_SETTINGS.environmentIdentificationMode, |
| 672 | 677 | glassOpacity: DEFAULT_UNIFIED_SETTINGS.glassOpacity, |
| 673 | 678 | sidebarThreadPreviewCount: DEFAULT_UNIFIED_SETTINGS.sidebarThreadPreviewCount, |
| ... | ... | @@ -1750,6 +1755,7 @@ function AutoSettleDaysInput({ |
| 1750 | 1755 | // expand the section before its target can mount and scroll. |
| 1751 | 1756 | const LEGACY_FEATURE_TARGET_IDS: ReadonlySet<string> = new Set([ |
| 1752 | 1757 | "legacy-plan-mode", |
| 1758 | "legacy-context-window-indicator", | |
| 1753 | 1759 | "legacy-token-streaming", |
| 1754 | 1760 | "legacy-sidebar", |
| 1755 | 1761 | ]); |
| ... | ... | @@ -1826,6 +1832,19 @@ function LegacyFeaturesSection() { |
| 1826 | 1832 | /> |
| 1827 | 1833 | } |
| 1828 | 1834 | /> |
| 1835 | <SettingsRow | |
| 1836 | {...searchableSetting("legacy-context-window-indicator")} | |
| 1837 | description="Shows context window usage as a circular indicator in the composer." | |
| 1838 | control={ | |
| 1839 | <Switch | |
| 1840 | checked={settings.contextWindowMeterEnabled} | |
| 1841 | onCheckedChange={(checked) => | |
| 1842 | updateSettings({ contextWindowMeterEnabled: Boolean(checked) }) | |
| 1843 | } | |
| 1844 | aria-label="Context window indicator (legacy)" | |
| 1845 | /> | |
| 1846 | } | |
| 1847 | /> | |
| 1829 | 1848 | <SettingsRow |
| 1830 | 1849 | serverScoped |
| 1831 | 1850 | {...searchableSetting("legacy-token-streaming")} |
apps/web/src/components/settings/settingsSearch.ts+6| ... | ... | @@ -261,6 +261,12 @@ export const SETTINGS_SEARCH_ITEMS = [ |
| 261 | 261 | to: "/settings/general", |
| 262 | 262 | searchTerms: ["build plan composer old"], |
| 263 | 263 | }, |
| 264 | { | |
| 265 | id: "legacy-context-window-indicator", | |
| 266 | title: "Context window indicator (legacy)", | |
| 267 | to: "/settings/general", | |
| 268 | searchTerms: ["composer meter usage tokens circle old"], | |
| 269 | }, | |
| 264 | 270 | { |
| 265 | 271 | id: "legacy-token-streaming", |
| 266 | 272 | title: "Stream token by token (legacy)", |
packages/contracts/src/settings.test.ts+12| ... | ... | @@ -191,6 +191,18 @@ describe("ClientSettings sidebar", () => { |
| 191 | 191 | }); |
| 192 | 192 | }); |
| 193 | 193 | |
| 194 | describe("ClientSettings context window meter", () => { | |
| 195 | it("defaults off and preserves an explicit legacy opt-in", () => { | |
| 196 | expect(decodeClientSettings({}).contextWindowMeterEnabled).toBe(false); | |
| 197 | expect( | |
| 198 | decodeClientSettings({ contextWindowMeterEnabled: true }).contextWindowMeterEnabled, | |
| 199 | ).toBe(true); | |
| 200 | expect( | |
| 201 | decodeClientSettingsPatch({ contextWindowMeterEnabled: true }).contextWindowMeterEnabled, | |
| 202 | ).toBe(true); | |
| 203 | }); | |
| 204 | }); | |
| 205 | ||
| 194 | 206 | describe("ServerSettings thread settlement", () => { |
| 195 | 207 | it("defaults merge settlement on and inactivity settlement to three days", () => { |
| 196 | 208 | const settings = decodeServerSettings({}); |
packages/contracts/src/settings.ts+4| ... | ... | @@ -265,6 +265,9 @@ export const ClientSettingsSchema = Schema.Struct({ |
| 265 | 265 | // default UI; this beta flag restores it (plus the /plan and /default slash |
| 266 | 266 | // commands) for users who still rely on the old workflow. |
| 267 | 267 | planModeEnabled: Schema.Boolean.pipe(Schema.withDecodingDefault(Effect.succeed(false))), |
| 268 | // Legacy context window meter. The composer hides it by default; users who | |
| 269 | // still want the old usage indicator can restore it from Settings. | |
| 270 | contextWindowMeterEnabled: Schema.Boolean.pipe(Schema.withDecodingDefault(Effect.succeed(false))), | |
| 268 | 271 | showSkillsInSlashMenu: Schema.Boolean.pipe(Schema.withDecodingDefault(Effect.succeed(true))), |
| 269 | 272 | // Legacy sidebar (the original per-project tree). Deliberately a fresh key |
| 270 | 273 | // (was `sidebarV2Enabled` + `sidebarV2ConfiguredByUser`): decoding drops the |
| ... | ... | @@ -990,6 +993,7 @@ export const ClientSettingsPatch = Schema.Struct({ |
| 990 | 993 | ), |
| 991 | 994 | ), |
| 992 | 995 | planModeEnabled: Schema.optionalKey(Schema.Boolean), |
| 996 | contextWindowMeterEnabled: Schema.optionalKey(Schema.Boolean), | |
| 993 | 997 | showSkillsInSlashMenu: Schema.optionalKey(Schema.Boolean), |
| 994 | 998 | legacySidebarEnabled: Schema.optionalKey(Schema.Boolean), |
| 995 | 999 | sidebarProjectGroupingMode: Schema.optionalKey(SidebarProjectGroupingMode), |