Merge remote-tracking branch 'origin/main' into port-2619
# Conflicts: # packages/ui/src/components/sections/openchamber/OpenChamberVisualSettings.tsx
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import type { SidebarSection } from '@/constants/sidebar';
|
||||
import type { IconName } from '@/components/icon/icons';
|
||||
|
||||
export type SettingsPageSlug =
|
||||
| 'home'
|
||||
@@ -24,7 +25,8 @@ export type SettingsPageSlug =
|
||||
| 'notifications'
|
||||
| 'voice'
|
||||
| 'tunnel'
|
||||
| 'about';
|
||||
| 'about'
|
||||
| 'integrations';
|
||||
|
||||
type SettingsPageGroup =
|
||||
| 'general'
|
||||
@@ -200,6 +202,7 @@ export const SETTINGS_PAGE_METADATA: readonly SettingsPageMeta[] = [
|
||||
{ slug: 'voice', title: 'Voice', group: 'general', kind: 'single', keywords: ['tts', 'speech', 'voice'], isAvailable: (ctx) => !ctx.isVSCode },
|
||||
{ slug: 'tunnel', title: 'External Tunnel', group: 'projects', kind: 'single', keywords: ['tunnel', 'external', 'cloudflare', 'qr', 'remote', 'mobile', 'share'], isAvailable: (ctx) => !ctx.isVSCode },
|
||||
{ slug: 'about', title: 'About', group: 'general', kind: 'single', keywords: ['about', 'version', 'updates', 'release', 'changelog'], isAvailable: (ctx) => ctx.isMobile && !ctx.isVSCode },
|
||||
{ slug: 'integrations', title: 'Integrations', group: 'general', kind: 'single', keywords: ['integration', 'plugin', 'provider', 'oauth', 'claude', 'cursor', 'command code', 'connect', 'discord', 'telegram', 'messenger'] },
|
||||
] as const;
|
||||
|
||||
const LEGACY_SIDEBAR_SECTION_TO_SETTINGS_SLUG: Record<SidebarSection, SettingsPageSlug> = {
|
||||
@@ -237,3 +240,68 @@ export function resolveSettingsSlug(value: string | null | undefined): SettingsP
|
||||
|
||||
return 'home';
|
||||
}
|
||||
|
||||
// Lives here (not in SettingsView) so light consumers such as the command
|
||||
// palette can render settings entries without statically importing the whole
|
||||
// settings surface into the eager startup graph.
|
||||
export function getSettingsNavIcon(slug: SettingsPageSlug): IconName | null {
|
||||
switch (slug) {
|
||||
case 'general':
|
||||
return 'settings-3';
|
||||
case 'projects':
|
||||
return 'folders';
|
||||
case 'remote-instances':
|
||||
return 'computer';
|
||||
case 'appearance':
|
||||
return 'palette';
|
||||
case 'chat':
|
||||
return 'chat-ai-3';
|
||||
case 'magic-prompts':
|
||||
return 'ai-generate-2';
|
||||
case 'snippets':
|
||||
return 'chat-thread';
|
||||
case 'notifications':
|
||||
return 'notification-3';
|
||||
case 'shortcuts':
|
||||
return 'command';
|
||||
case 'sessions':
|
||||
return 'chat-history';
|
||||
|
||||
case 'providers':
|
||||
return 'cloud';
|
||||
case 'agents':
|
||||
return 'ai-agent';
|
||||
case 'behavior':
|
||||
return 'brain';
|
||||
case 'commands':
|
||||
return 'slash-commands-2';
|
||||
case 'mcp':
|
||||
return null;
|
||||
case 'plugins':
|
||||
return 'plug-2';
|
||||
|
||||
case 'skills.installed':
|
||||
return 'book-open';
|
||||
case 'skills.catalog':
|
||||
return 'book';
|
||||
|
||||
case 'git':
|
||||
return 'git-branch';
|
||||
|
||||
case 'integrations':
|
||||
return 'plug';
|
||||
|
||||
case 'usage':
|
||||
return 'bar-chart-2';
|
||||
case 'voice':
|
||||
return 'mic';
|
||||
case 'tunnel':
|
||||
return 'home-office';
|
||||
case 'about':
|
||||
return 'information';
|
||||
case 'home':
|
||||
return null;
|
||||
default:
|
||||
return 'robot-2';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
import { describe, expect, test } from 'bun:test';
|
||||
import type { I18nKey } from '@/lib/i18n/store';
|
||||
import { buildSettingsSearchResults } from './search';
|
||||
|
||||
const t = (key: I18nKey): string => key;
|
||||
|
||||
const runtimeCtx = {
|
||||
isVSCode: false,
|
||||
isWeb: true,
|
||||
isDesktop: false,
|
||||
isMobile: false,
|
||||
isDesktopLocalOrigin: false,
|
||||
isMac: false,
|
||||
isWindows: false,
|
||||
isLinux: false,
|
||||
isWindowsArm64: false,
|
||||
};
|
||||
|
||||
describe('settings search', () => {
|
||||
test('finds the Claude Code third-party integration', () => {
|
||||
const results = buildSettingsSearchResults({
|
||||
query: 'claude',
|
||||
runtimeCtx,
|
||||
t,
|
||||
getPageTitle: (page) => page,
|
||||
});
|
||||
|
||||
expect(results.some((result) => result.id === 'integrations.third-party.opencode-claude')).toBe(true);
|
||||
});
|
||||
|
||||
test('finds third-party integrations by OpenChamber npm package names', () => {
|
||||
const results = buildSettingsSearchResults({
|
||||
query: '@openchamber/opencode-cursor',
|
||||
runtimeCtx,
|
||||
t,
|
||||
getPageTitle: (page) => page,
|
||||
});
|
||||
|
||||
expect(results.some((result) => result.id === 'integrations.third-party.opencode-cursor-oauth')).toBe(true);
|
||||
});
|
||||
});
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { I18nKey } from '@/lib/i18n/store';
|
||||
import { useUIStore } from '@/stores/useUIStore';
|
||||
import type { SettingsPageSlug, SettingsRuntimeContext } from './metadata';
|
||||
import { getSettingsPageMeta } from './metadata';
|
||||
|
||||
@@ -49,7 +50,6 @@ const SETTINGS_SEARCH_ITEMS: readonly SettingsSearchItem[] = [
|
||||
page: 'appearance',
|
||||
titleKey: 'settings.openchamber.visual.field.weekStartsOn',
|
||||
keywords: ['calendar', 'monday', 'sunday'],
|
||||
isAvailable: (ctx) => !ctx.isVSCode,
|
||||
},
|
||||
{
|
||||
id: 'appearance.light-theme',
|
||||
@@ -65,14 +65,6 @@ const SETTINGS_SEARCH_ITEMS: readonly SettingsSearchItem[] = [
|
||||
keywords: ['theme', 'color', 'dark mode'],
|
||||
isAvailable: (ctx) => !ctx.isVSCode,
|
||||
},
|
||||
{
|
||||
id: 'appearance.window-transparency',
|
||||
page: 'appearance',
|
||||
titleKey: 'settings.openchamber.visual.field.macVibrancy',
|
||||
descriptionKey: 'settings.openchamber.visual.field.macVibrancyHint',
|
||||
keywords: ['transparent', 'transparency', 'vibrancy', 'blur', 'macos', 'opaque'],
|
||||
isAvailable: (ctx) => ctx.isDesktopLocalOrigin,
|
||||
},
|
||||
{
|
||||
id: 'appearance.dock-badge',
|
||||
page: 'appearance',
|
||||
@@ -156,19 +148,20 @@ const SETTINGS_SEARCH_ITEMS: readonly SettingsSearchItem[] = [
|
||||
descriptionKey: 'settings.openchamber.visual.field.autoSaveEnabledInfo',
|
||||
keywords: ['editor', 'autosave', 'auto-save', 'files', 'save'],
|
||||
},
|
||||
{
|
||||
id: 'appearance.expanded-editor-toolbar',
|
||||
page: 'general',
|
||||
titleKey: 'settings.openchamber.visual.field.expandedEditorToolbar',
|
||||
keywords: ['editor', 'toolbar', 'tabs', 'docked', 'files'],
|
||||
isAvailable: (ctx) => !ctx.isVSCode,
|
||||
},
|
||||
{
|
||||
id: 'appearance.file-editor-keymap',
|
||||
page: 'general',
|
||||
titleKey: 'settings.openchamber.visual.field.fileEditorKeymap',
|
||||
keywords: ['editor', 'vim', 'keymap'],
|
||||
},
|
||||
{
|
||||
id: 'appearance.session-tabs',
|
||||
page: 'general',
|
||||
titleKey: 'settings.openchamber.visual.field.sessionTabsGroup',
|
||||
descriptionKey: 'settings.openchamber.visual.field.sessionTabsInfo',
|
||||
keywords: ['session', 'tabs', 'header', 'working set'],
|
||||
isAvailable: (ctx) => !ctx.isMobile && !ctx.isVSCode,
|
||||
},
|
||||
{
|
||||
id: 'appearance.terminal-quick-keys',
|
||||
page: 'general',
|
||||
@@ -184,6 +177,13 @@ const SETTINGS_SEARCH_ITEMS: readonly SettingsSearchItem[] = [
|
||||
descriptionKey: 'settings.openchamber.visual.field.sendAnonymousUsageReportsHint',
|
||||
keywords: ['telemetry', 'analytics'],
|
||||
},
|
||||
{
|
||||
id: 'general.app-links',
|
||||
page: 'general',
|
||||
titleKey: 'settings.openchamber.appLinks.title',
|
||||
descriptionKey: 'settings.openchamber.appLinks.info',
|
||||
keywords: ['security', 'app link', 'deep link', 'scheme', 'protocol', 'obsidian', 'notion'],
|
||||
},
|
||||
{
|
||||
id: 'chat.render-mode',
|
||||
page: 'chat',
|
||||
@@ -240,6 +240,19 @@ const SETTINGS_SEARCH_ITEMS: readonly SettingsSearchItem[] = [
|
||||
titleKey: 'settings.openchamber.visual.section.reasoning',
|
||||
keywords: ['thinking', 'traces'],
|
||||
},
|
||||
{
|
||||
id: 'chat.streaming',
|
||||
page: 'chat',
|
||||
titleKey: 'settings.openchamber.visual.section.streaming',
|
||||
keywords: ['stream', 'scroll'],
|
||||
},
|
||||
{
|
||||
id: 'chat.streaming-auto-follow',
|
||||
page: 'chat',
|
||||
titleKey: 'settings.openchamber.visual.field.streamingAutoFollow',
|
||||
descriptionKey: 'settings.openchamber.visual.field.streamingAutoFollowInfo',
|
||||
keywords: ['autoscroll', 'auto-scroll', 'follow', 'stick to bottom', 'streaming'],
|
||||
},
|
||||
{
|
||||
id: 'chat.sticky-user-header',
|
||||
page: 'chat',
|
||||
@@ -491,11 +504,29 @@ const SETTINGS_SEARCH_ITEMS: readonly SettingsSearchItem[] = [
|
||||
{
|
||||
id: 'sessions.agent-control-tool',
|
||||
page: 'general',
|
||||
titleKey: 'settings.openchamber.opencodeCli.field.agentControlTool',
|
||||
descriptionKey: 'settings.openchamber.opencodeCli.field.agentControlToolInfo',
|
||||
titleKey: 'settings.openchamber.tools.field.agentControlTool',
|
||||
descriptionKey: 'settings.openchamber.tools.field.agentControlToolInfo',
|
||||
keywords: ['agent', 'tool', 'orchestration', 'openchamber', 'sessions', 'schedule', 'control'],
|
||||
isAvailable: (ctx) => !ctx.isVSCode,
|
||||
},
|
||||
{
|
||||
id: 'sessions.agent-web-tool',
|
||||
page: 'general',
|
||||
titleKey: 'settings.openchamber.tools.field.agentWebTool',
|
||||
descriptionKey: 'settings.openchamber.tools.field.agentWebToolInfo',
|
||||
keywords: ['agent', 'tool', 'web', 'browser', 'page', 'preview', 'openchamber'],
|
||||
isAvailable: (ctx) => !ctx.isVSCode,
|
||||
},
|
||||
{
|
||||
id: 'sessions.agent-memory-tool',
|
||||
page: 'general',
|
||||
titleKey: 'settings.openchamber.tools.field.agentMemoryTool',
|
||||
descriptionKey: 'settings.openchamber.tools.field.agentMemoryToolInfo',
|
||||
keywords: ['agent', 'tool', 'memory', 'remember', 'recall', 'preferences', 'openchamber'],
|
||||
// Unreleased: searching for a setting that is not rendered would take the
|
||||
// user to an empty spot on the page.
|
||||
isAvailable: (ctx) => !ctx.isVSCode && useUIStore.getState().agentMemoryFeatureAvailable,
|
||||
},
|
||||
{
|
||||
id: 'git.github-account',
|
||||
page: 'git',
|
||||
@@ -528,11 +559,11 @@ const SETTINGS_SEARCH_ITEMS: readonly SettingsSearchItem[] = [
|
||||
keywords: ['ignored', 'files', 'gitignore'],
|
||||
},
|
||||
{
|
||||
id: 'usage.header-menu',
|
||||
id: 'usage.work-status-panel',
|
||||
page: 'usage',
|
||||
titleKey: 'settings.usage.page.options.showInHeader',
|
||||
descriptionKey: 'settings.usage.page.options.showInHeaderTooltip',
|
||||
keywords: ['quota', 'header', 'dropdown'],
|
||||
titleKey: 'settings.usage.page.options.showInWorkStatus',
|
||||
descriptionKey: 'settings.usage.page.options.showInWorkStatusTooltip',
|
||||
keywords: ['quota', 'work', 'status', 'panel'],
|
||||
},
|
||||
{
|
||||
id: 'usage.model-quotas',
|
||||
@@ -546,6 +577,18 @@ const SETTINGS_SEARCH_ITEMS: readonly SettingsSearchItem[] = [
|
||||
titleKey: 'settings.projects.page.field.projectName',
|
||||
keywords: ['label', 'display name', 'project metadata'],
|
||||
},
|
||||
{
|
||||
id: 'projects.default-model',
|
||||
page: 'projects',
|
||||
titleKey: 'settings.projects.page.field.projectModel',
|
||||
keywords: ['model', 'default', 'new chat', 'project metadata'],
|
||||
},
|
||||
{
|
||||
id: 'projects.default-thinking',
|
||||
page: 'projects',
|
||||
titleKey: 'settings.projects.page.field.projectThinking',
|
||||
keywords: ['thinking', 'variant', 'reasoning', 'effort', 'model', 'project metadata'],
|
||||
},
|
||||
{
|
||||
id: 'projects.accent-color',
|
||||
page: 'projects',
|
||||
@@ -940,6 +983,27 @@ const SETTINGS_SEARCH_ITEMS: readonly SettingsSearchItem[] = [
|
||||
keywords: ['background', 'push'],
|
||||
isAvailable: (ctx) => ctx.isWeb && !ctx.isDesktop && !ctx.isVSCode,
|
||||
},
|
||||
|
||||
{
|
||||
id: 'integrations.third-party',
|
||||
page: 'integrations',
|
||||
titleKey: 'settings.integrations.thirdParty.title',
|
||||
keywords: ['plugin', 'provider', 'oauth', 'install', 'update', 'remove'],
|
||||
},
|
||||
{
|
||||
id: 'integrations.third-party.opencode-claude',
|
||||
page: 'integrations',
|
||||
titleKey: 'settings.integrations.thirdParty.opencodeClaude.name',
|
||||
descriptionKey: 'settings.integrations.thirdParty.opencodeClaude.description',
|
||||
keywords: ['claude', 'anthropic', 'claude code', 'pro', 'max', 'agent sdk', '@openchamber/opencode-claude'],
|
||||
},
|
||||
{
|
||||
id: 'integrations.third-party.opencode-cursor-oauth',
|
||||
page: 'integrations',
|
||||
titleKey: 'settings.integrations.thirdParty.opencodeCursorOauth.name',
|
||||
descriptionKey: 'settings.integrations.thirdParty.opencodeCursorOauth.description',
|
||||
keywords: ['cursor', 'oauth', 'subscription', 'openai compatible', '@openchamber/opencode-cursor'],
|
||||
},
|
||||
] as const;
|
||||
|
||||
interface BuildSettingsSearchResultsOptions {
|
||||
|
||||
Reference in New Issue
Block a user