### Quick Start: Data API, Preferences, and Cache Hooks
Source: https://github.com/cherryhq/cherry-studio/blob/main/src/renderer/data/README.md
Demonstrates the basic setup for using Data API hooks (useQuery, useMutation), Preference hooks (usePreference), and Cache hooks (useCache, useSharedCache, usePersistCache).
```typescript
// Data API
import { useQuery, useMutation } from '@data/hooks/useDataApi'
const { data } = useQuery('/topics')
const { trigger: createTopic } = useMutation('/topics', 'POST')
// Preferences
import { usePreference } from '@data/hooks/usePreference'
const [theme, setTheme] = usePreference('app.theme.mode')
// Cache (three-tier renderer cache)
import { useCache, useSharedCache, usePersistCache } from '@data/hooks/useCache'
const [counter, setCounter] = useCache('ui.counter', 0)
// Non-reactive DataApi cache control (snapshot read / overlay write / invalidate)
import { useReadCache, useWriteCache, useInvalidateCache } from '@data/hooks/useDataApi'
```
--------------------------------
### Example Boot Configuration JSON
Source: https://github.com/cherryhq/cherry-studio/blob/main/docs/references/data/boot-config-overview.md
This JSON object represents the boot configuration file. It includes settings like disabling hardware acceleration and defining user data paths for different application installations.
```json
{
"app.disable_hardware_acceleration": false,
"app.user_data_path": {
"/Applications/Cherry Studio.app/Contents/MacOS/Cherry Studio": "/Volumes/External/CherryData"
}
}
```
--------------------------------
### Example Window Type Configuration with Quirks
Source: https://github.com/cherryhq/cherry-studio/blob/main/docs/references/window-manager/window-manager-platform.md
Demonstrates how to configure a specific window type with various behavior and OS-specific quirks. This setup allows for declarative control over window appearance and interaction across platforms, particularly macOS.
```typescript
[WindowType.SelectionToolbar]: {
type: WindowType.SelectionToolbar,
lifecycle: 'singleton',
showMode: 'manual',
windowOptions: { /* ... */ },
behavior: {
hideOnBlur: true,
alwaysOnTop: { level: 'screen-saver' }, // level lives here, not in quirks
visibleOnAllWorkspaces: { enabled: true, visibleOnFullScreen: true },
macShowInDock: false
},
quirks: {
macRestoreFocusOnHide: true,
macClearHoverOnHide: true,
macReapplyAlwaysOnTop: true // boolean switch; reads level from behavior above
}
}
```
--------------------------------
### Install @cherrystudio/ai-sdk-provider
Source: https://github.com/cherryhq/cherry-studio/blob/main/packages/ai-sdk-provider/README.md
Install the provider along with the required peer dependencies using npm or pnpm.
```bash
npm install ai @cherrystudio/ai-sdk-provider @ai-sdk/anthropic @ai-sdk/google @ai-sdk/openai
# or
pnpm add ai @cherrystudio/ai-sdk-provider @ai-sdk/anthropic @ai-sdk/google @ai-sdk/openai
```
--------------------------------
### Copy Zed Settings Example
Source: https://github.com/cherryhq/cherry-studio/blob/main/docs/guides/development.md
Copy the example settings file to your local Zed configuration. Customize the copied file as needed.
```bash
cp .zed/settings.json.example .zed/settings.json
```
--------------------------------
### Start Development Server
Source: https://github.com/cherryhq/cherry-studio/blob/main/docs/guides/development.md
Start the development server using pnpm. This command is used for local development and testing.
```bash
pnpm dev
```
--------------------------------
### Install Project Dependencies
Source: https://github.com/cherryhq/cherry-studio/blob/main/docs/guides/development.md
Install all project dependencies using pnpm. This command should be run after cloning the repository.
```bash
pnpm install
```
--------------------------------
### Format Skill Examples
Source: https://github.com/cherryhq/cherry-studio/blob/main/resources/skills/skill-creator/SKILL.md
Format examples using a clear Input/Output structure, deviating slightly if 'Input' and 'Output' are already present in the example context.
```markdown
## Commit message format
**Example 1:**
Input: Added user authentication with JWT tokens
Output: feat(auth): implement JWT-based authentication
```
--------------------------------
### Install Node.js Version
Source: https://github.com/cherryhq/cherry-studio/blob/main/docs/guides/development.md
Install the required Node.js version for the project using nvm. Ensure nvm is installed and configured.
```bash
nvm install
```
--------------------------------
### Copy Environment Variables Example
Source: https://github.com/cherryhq/cherry-studio/blob/main/docs/guides/development.md
Copy the example environment file to create a new .env file. This file should be customized with project-specific settings.
```bash
cp .env.example .env
```
--------------------------------
### Install Cherry Studio UI
Source: https://github.com/cherryhq/cherry-studio/blob/main/packages/ui/README.md
Install the Cherry Studio UI package and its peer dependencies using npm.
```bash
npm install @cherrystudio/ui
# peer dependencies
npm install framer-motion react react-dom tailwindcss
```
--------------------------------
### CLI Structure Example
Source: https://github.com/cherryhq/cherry-studio/blob/main/docs/references/feishu-notify.md
Basic command structure for running the Feishu notification script.
```bash
pnpm tsx scripts/feishu-notify.ts [command] [options]
```
--------------------------------
### Start Debugger
Source: https://github.com/cherryhq/cherry-studio/blob/main/docs/guides/development.md
Start the application in debug mode using pnpm. Access the debugger by navigating to chrome://inspect in your browser.
```bash
pnpm debug
```
--------------------------------
### Mode 1: Full Theme Contract React Example
Source: https://github.com/cherryhq/cherry-studio/blob/main/packages/ui/README.md
Example of using Cherry Studio UI components with the full theme contract. Utility classes like `bg-primary`, `p-md`, and `rounded-lg` resolve to Cherry Studio's design values.
```tsx
{/* Extended utility classes */}
Tiny spacing (0.5rem)
Extra small spacing (1rem)
Small spacing (1.5rem)
Medium spacing (2.5rem)
Large spacing (3.5rem)
Extra large spacing (5rem)
Maximum spacing (15rem)
Tiny radius (0.03125rem)
Small radius (0.125rem)
Medium radius (0.5rem)
Large radius (0.875rem)
Full radius (999px)
```
--------------------------------
### Display skill information
Source: https://github.com/cherryhq/cherry-studio/blob/main/resources/skills/find-skills/SKILL.md
When skills are found, the command output provides installation instructions and a link to the skill's source repository. This information is crucial for users to review before installation.
```bash
Install with npx skills add
vercel-labs/agent-skills@vercel-react-best-practices
└ https://skills.sh/vercel-labs/agent-skills/vercel-react-best-practices
```
--------------------------------
### Install a skill
Source: https://github.com/cherryhq/cherry-studio/blob/main/resources/skills/find-skills/SKILL.md
After reviewing the skill's source and confirming with the user, use the `npx skills add` command to install it. The `-y` flag is used for non-interactive execution, but user confirmation is mandatory.
```bash
npx skills add -y
```
--------------------------------
### Diffusion Emitter Example
Source: https://github.com/cherryhq/cherry-studio/blob/main/docs/references/ai/image-generation-parameters.md
Example of the 'diffusion' emitter (default for silicon, zhipu, openrouter, etc.) handling parameters in snake_case, such as negative_prompt, seed, num_inference_steps, guidance_scale, prompt_enhancement, and quality.
```typescript
// silicon / zhipu / openrouter / …, the default → snake_case { negative_prompt, seed, num_inference_steps, guidance_scale, prompt_enhancement, quality }.
```
--------------------------------
### Stop, Start, and Restart Services
Source: https://github.com/cherryhq/cherry-studio/blob/main/docs/references/lifecycle/lifecycle-usage.md
All services support basic stop, start, and restart operations. Use these methods to control the lifecycle of a service instance.
```typescript
import { application } from '@application'
await application.stop('HeavyComputeService') // calls onStop()
await application.start('HeavyComputeService') // calls onInit() again
await application.restart('HeavyComputeService') // stop + start
```
--------------------------------
### Canonical Setup for Lifecycle Service Testing
Source: https://github.com/cherryhq/cherry-studio/blob/main/tests/__mocks__/README.md
Provides a canonical setup for stubbing feature-specific lifecycle services locally in test files. This includes mocking dependencies and the BaseService.
```typescript
import type * as LifecycleModule from '@main/core/lifecycle'
import { getDependencies, getPhase } from '@main/core/lifecycle/decorators'
import { Phase } from '@main/core/lifecycle/types'
import { beforeEach, describe, expect, it, vi } from 'vitest'
const { appGetMock, startTaskMock, getTaskMock } = vi.hoisted(() => ({
appGetMock: vi.fn(),
startTaskMock: vi.fn(),
getTaskMock: vi.fn()
}))
vi.mock('@application', () => ({
application: { get: appGetMock }
}))
vi.mock('@main/core/lifecycle', async (importOriginal) => {
const actual = await importOriginal()
class MockBaseService {
ipcHandle = vi.fn()
protected readonly _disposables: Array<{ dispose: () => void } | (() => void)> = []
protected registerDisposable void } | (() => void)>(d: T): T {
this._disposables.push(d)
return d
}
}
return { ...actual, BaseService: MockBaseService }
})
beforeEach(() => {
vi.clearAllMocks()
appGetMock.mockImplementation((name: string) => {
if (name === 'FileProcessingTaskService') {
return { startTask: startTaskMock, getTask: getTaskMock }
}
throw new Error(`Unexpected application.get(${name})`)
})
})
// Import SUT after mocks are declared.
const { FileProcessingService } = await import('../FileProcessingService')
```
--------------------------------
### Package the skill
Source: https://github.com/cherryhq/cherry-studio/blob/main/resources/skills/skill-creator/SKILL.md
Packages a skill folder into a .skill file for installation, provided the present_files tool is available.
```bash
python -m scripts.package_skill
```
--------------------------------
### Register, Bootstrap, and Access Services
Source: https://github.com/cherryhq/cherry-studio/blob/main/docs/references/lifecycle/application-overview.md
This snippet shows the basic workflow for initializing the application by registering all services, bootstrapping the system, and then accessing a specific service.
```typescript
import { application, serviceList } from '@application'
// 1. Register all services
application.registerAll(serviceList)
// 2. Bootstrap (handles all three phases + Electron lifecycle)
await application.bootstrap()
// 3. Access a service
const dbService = application.get('DbService')
```
--------------------------------
### DirectoryWatcher Usage Pattern
Source: https://github.com/cherryhq/cherry-studio/blob/main/docs/references/file/file-manager-architecture.md
Illustrative example of how a business module might instantiate and use a DirectoryWatcher. This pattern involves creating an instance, setting up event listeners, starting the watcher, and ensuring it's disposed of.
```typescript
// Illustrative (non-file_module implementation)
const watcher = new DirectoryWatcher({
path: source.basePath,
renameDetection: { enabled: true }
})
watcher.onAdd(...)
watcher.onRename(...)
await watcher.start()
// ...
watcher.dispose()
```
--------------------------------
### Parallel Initialization Example
Source: https://github.com/cherryhq/cherry-studio/blob/main/docs/references/lifecycle/lifecycle-overview.md
Illustrates how services within the same phase are initialized in parallel if they have no inter-dependencies, forming layers of sequential execution.
```text
Phase: WhenReady
Layer 1: [DbService, ConfigService] <- parallel (no inter-dependency)
Layer 2: [PreferenceService] <- sequential (depends on layer 1)
Layer 3: [MainWindowService] <- sequential (depends on layer 2)
```
--------------------------------
### Pooled Window Configuration for SelectionAction
Source: https://github.com/cherryhq/cherry-studio/blob/main/docs/references/window-manager/window-manager-overview.md
Example of configuring a window type for the 'pooled' lifecycle. This setup maintains a pre-warmed spare and recycles up to three windows for burst handling, with specific decay and inactivity timeouts.
```typescript
WINDOW_TYPE_REGISTRY[WindowType.SelectionAction] = {
type: WindowType.SelectionAction,
lifecycle: 'pooled',
htmlPath: 'selectionAction.html',
poolConfig: {
standbySize: 1,
recycleMaxSize: 3,
decayInterval: 60,
inactivityTimeout: 300,
warmup: 'eager'
},
windowOptions: { ...DEFAULT_WINDOW_CONFIG, width: 400, height: 300 },
}
```
--------------------------------
### Run Storybook Development Server
Source: https://github.com/cherryhq/cherry-studio/blob/main/packages/ui/stories/README.md
Navigate to the 'packages/ui' directory and execute this command to start the Storybook server. Access the component documentation at the provided localhost URL.
```bash
cd packages/ui
pnpm storybook
```
--------------------------------
### Mock Main DbService Setup
Source: https://github.com/cherryhq/cherry-studio/blob/main/tests/__mocks__/README.md
Resets mock DbService instances before each test and provides utilities to get the default mock DB or set a custom one. Ensure your hand-rolled DbService mocks include the 'withWriteTx' method.
```typescript
import { MockMainDbServiceUtils } from '@test-mocks/main/DbService'
beforeEach(() => MockMainDbServiceUtils.resetMocks())
// Use default mock db
MockMainDbServiceUtils.getDefaultMockDb()
// Replace with custom db
MockMainDbServiceUtils.setDb(customMockDb)
```
--------------------------------
### Preset File Naming Convention Example
Source: https://github.com/cherryhq/cherry-studio/blob/main/docs/references/data/best-practice-layered-preset-pattern.md
Demonstrates the naming correspondence between preset files and their corresponding constants.
```text
providers.ts → PRESETS_PROVIDERS
selection-actions.ts → PRESETS_SELECTION_ACTIONS
ai-models.ts → PRESETS_AI_MODELS
```
--------------------------------
### Attach Listeners Directly at open() Call Site (Anti-pattern)
Source: https://github.com/cherryhq/cherry-studio/blob/main/docs/references/window-manager/window-manager-usage.md
This example shows an anti-pattern of attaching listeners directly after calling `wm.open()`. This can lead to duplicate listeners if the window is reused and requires manual setup across multiple entry points.
```typescript
const id = wm.open(WindowType.Settings)
const window = wm.getWindow(id)!
window.on('blur', this.hideIfUnpinned)
window.once('closed', () => { this.windowId = null })
```
--------------------------------
### Boot Timing Sequence Diagram
Source: https://github.com/cherryhq/cherry-studio/blob/main/docs/references/data/boot-config-overview.md
Illustrates the application startup sequence, highlighting when the BootConfig system is loaded and its dependencies relative to other lifecycle phases.
```text
┌──────────────────────────────────────────────────────────────────────┐
│ App Startup Sequence │
│ │
│ 1. BootConfig load ← Sync read of boot-config.json │
│ (bootConfigService) Only data system available here │
│ │ │
│ 2. Bootstrap ← App data directory setup │
│ │ │
│ 3. application.bootstrap() │
│ │ │
│ ├── Background phase (fire-and-forget) │
│ │ │
│ ├── Promise.all([
│ │ BeforeReady phase, ← DB init, PreferenceService, │
│ │ app.whenReady() CacheService, DataApiService │
│ │ ]) │
│ │ │
│ └── WhenReady phase ← Window creation, IPC handlers │
│ │
└──────────────────────────────────────────────────────────────────────┘
```
--------------------------------
### Get Database File Size (Sync)
Source: https://github.com/cherryhq/cherry-studio/blob/main/v2-refactor-temp/docs/file-manager/fs-usage-audit.md
Use `fs.statSync()` to synchronously get the size of a database file.
```typescript
fs.statSync()
```
--------------------------------
### Build Project
Source: https://github.com/cherryhq/cherry-studio/blob/main/packages/provider-registry/README.md
Execute the build command for the provider-registry package. This command compiles the project's source code.
```bash
pnpm build
```
--------------------------------
### Invalid Dependency Warning Example
Source: https://github.com/cherryhq/cherry-studio/blob/main/docs/references/lifecycle/lifecycle-overview.md
Example of a warning log message when an invalid dependency is declared and automatically corrected.
```text
[WARN] Service 'X' declared as Background but depends on BeforeReady service 'Y', adjusted to BeforeReady
```
--------------------------------
### Console Timing Start
Source: https://github.com/cherryhq/cherry-studio/blob/main/src/renderer/windows/main/index.html
Starts a timer in the browser's console to measure the duration of the application initialization process.
```javascript
console.time('init')
```
--------------------------------
### File Manager Data Fetching and Rendering Examples
Source: https://github.com/cherryhq/cherry-studio/blob/main/v2-refactor-temp/docs/file-manager/rfc-file-manager.md
Demonstrates how to fetch file entries, reference counts, dangling states, and physical paths using useQuery. It also shows how to construct preview URLs and handle agent composition requiring absolute paths. This pattern uses explicit useQuery for each enrichment, making costs visible.
```typescript
// 案例 1:FilesPage 列表 + 引用计数 + dangling + preview URL
const { data: entries } = useQuery(fileApi.listEntries, { origin: "internal" });
const entryIds = entries?.map((e) => e.id) ?? [];
const { data: refCounts } = useQuery(fileApi.refCounts, { entryIds });
const { data: presence } = useQuery(
["fileManager.batchGetDanglingStates", entryIds],
() => window.api.fileManager.batchGetDanglingStates(entryIds),
{ enabled: entryIds.length > 0 }
);
const { data: paths } = useQuery(
["fileManager.batchGetPhysicalPaths", entryIds],
() => window.api.fileManager.batchGetPhysicalPaths(entryIds),
{ enabled: entryIds.length > 0 }
);
// renderer 合并后按 refCount 排序
// URL 在进程内合成(共享纯函数,零 IPC):
//
// dangling 标记:presence?.[entry.id]
```
```typescript
// 案例 2:Agent compose 需要绝对路径(复用同一 IPC,不同 consumer)
const { data: entries } = useQuery(fileApi.listEntries, { ids: selectedFileIds });
const { data: paths } = useQuery(
["fileManager.batchGetPhysicalPaths", selectedFileIds],
() => window.api.fileManager.batchGetPhysicalPaths(selectedFileIds)
);
const filePaths = selectedFileIds.map((id) => paths?.[id]).filter(Boolean).join("\n");
```
--------------------------------
### Google Emitter Example
Source: https://github.com/cherryhq/cherry-studio/blob/main/docs/references/ai/image-generation-parameters.md
Example of the 'google' emitter handling parameters within 'imageConfig' for aspectRatio and imageSize, and 'personGeneration' for Imagen.
```typescript
// imageConfig.{aspectRatio, imageSize} + Imagen imageConfig.personGeneration (lowercased for the AI SDK schema).
```
--------------------------------
### File Tree Creation and Disposal Example
Source: https://github.com/cherryhq/cherry-studio/blob/main/docs/references/file/directory-tree.md
Illustrates how unique treeIds are generated for file tree creations and how disposal affects builder reference counts. Demonstrates the grace timer mechanism for builder teardown.
```text
File_TreeCreate('/work/notes', {...}) → treeId=t-1
File_TreeCreate('/work/notes', {...}) → treeId=t-2 ← same builder
File_TreeCreate('/work/code', {...}) → treeId=t-3 ← new builder
Tear down t-1 → refcount on (/work/notes) builder = 1
Tear down t-2 → refcount = 0, grace timer queued
T+500ms: timer fires → builder.dispose() → watcher FDs released
```
--------------------------------
### FileManager Startup Timeline
Source: https://github.com/cherryhq/cherry-studio/blob/main/docs/references/file/architecture.md
Visualizes the startup sequence, showing the progression from DbService in BeforeReady to FileManager's onInit in WhenReady, and the on-demand execution of runSweep.
```typescript
BeforeReady
|
DbService
|
app.whenReady()
|
v WhenReady
FileManager.onInit():
1. await DanglingCache.initFromDb()
(SELECT id, externalPath FROM file_entry
WHERE origin='external'
— external rows are never trashed by invariant)
2. this.registerIpcHandlers()
(wires File_GetDanglingState +
File_BatchGetDanglingStates + File_RunSweep;
other File_* channels land in Phase 2)
(version cache constructs at field-init time;
§3.6 broadcast wiring is deferred to Phase 2)
│
(ready signal emitted immediately)
│
▼
onAllReady()
│
▼ (on-demand, when cleanup UI calls File_RunSweep)
FileManager.runSweep — runs concurrently:
• FS-level: UUID files not in DB → unlink,
*.tmp- → unlink
• DB-level: orphan-ref deletion + orphan-entry report
(uuid here is v4 from node:crypto.randomUUID;
orphan sweep regex is version-agnostic)
```
--------------------------------
### Get Download URI Utility
Source: https://github.com/cherryhq/cherry-studio/blob/main/resources/skills/skill-creator/eval-viewer/viewer.html
A utility function to get the download URI for a file. It prioritizes data_uri, otherwise uses data_b64.
```javascript
function getDownloadUri(file) {
if (file.data_uri) return file.data_uri;
if (file.data_b64) return "data:application/octet-stream;base64,";
}
```
--------------------------------
### Initialize a new skill
Source: https://github.com/cherryhq/cherry-studio/blob/main/resources/skills/find-skills/SKILL.md
Use this command to scaffold a new skill project when no existing skill meets your requirements.
```bash
npx skills init my-xyz-skill
```
--------------------------------
### Global Mock Application Setup
Source: https://github.com/cherryhq/cherry-studio/blob/main/tests/__mocks__/README.md
Configures a global mock for the application module using mockApplicationFactory. This is typically done once in the test setup file.
```typescript
vi.mock('@application', async () => {
const { mockApplicationFactory } = await import('./__mocks__/main/application')
return mockApplicationFactory()
})
```
--------------------------------
### Basic Navigation Example
Source: https://github.com/cherryhq/cherry-studio/blob/main/src/main/ai/mcp/servers/browser/README.md
Opens a URL in a browser window using the 'open' tool in normal mode, where data persists across restarts.
```typescript
await controller.open('https://example.com')
```
--------------------------------
### Example: Adding Default Values for New Preferences
Source: https://github.com/cherryhq/cherry-studio/blob/main/docs/references/data/preference-schema-guide.md
Illustrates how to provide default values for the newly added preference keys in `DefaultPreferences`.
```typescript
export const DefaultPreferences: PreferenceSchemas = {
default: {
// ...existing defaults (alphabetically sorted)...
'feature.my_feature.enabled': true,
'feature.my_feature.mode': PreferenceTypes.MyFeatureMode.auto,
}
}
```
--------------------------------
### Renderer IPC Invocation Example
Source: https://github.com/cherryhq/cherry-studio/blob/main/docs/references/window-manager/window-manager-api-reference.md
Example of how a renderer process can invoke Window Manager methods via IPC. This pattern is used for most window operations.
```typescript
import { IpcChannel } from "@/shared/IpcChannel";
// Example for opening a window
const windowId = await window.electron.ipcRenderer.invoke(IpcChannel.WindowManager_Open, "my-window-type", { initData: "some data" });
// Example for closing a window
const success = await window.electron.ipcRenderer.invoke(IpcChannel.WindowManager_Close, "my-window-type");
// Example for showing a window
await window.electron.ipcRenderer.invoke(IpcChannel.WindowManager_Show, "my-window-type");
// Example for hiding a window
await window.electron.ipcRenderer.invoke(IpcChannel.WindowManager_Hide, "my-window-type");
// Example for minimizing a window
await window.electron.ipcRenderer.invoke(IpcChannel.WindowManager_Minimize, "my-window-type");
// Example for maximizing a window
await window.electron.ipcRenderer.invoke(IpcChannel.WindowManager_Maximize, "my-window-type");
// Example for focusing a window
await window.electron.ipcRenderer.invoke(IpcChannel.WindowManager_Focus, "my-window-type");
```
--------------------------------
### Agent Initialization and Streaming
Source: https://github.com/cherryhq/cherry-studio/blob/main/docs/references/ai/agent-loop.md
Initializes an Agent instance with provider details, plugins, and hooks. Demonstrates how to initiate a streaming response from the agent.
```typescript
const agent = new Agent({
providerId,
providerSettings,
modelId,
plugins,
tools,
system,
options,
hookParts, // RequestFeature contributions
messageId // stable id for the first emitted UIMessage
})
const stream: ReadableStream = agent.stream(initialMessages, signal)
// or (non-streaming; input is { prompt } | { messages })
const result = await agent.generate({ messages }, signal)
// internal observers can also register on the agent:
const dispose = agent.on('onStepFinish', step => { … })
```
--------------------------------
### Command Definition Example
Source: https://github.com/cherryhq/cherry-studio/blob/main/docs/references/command/README.md
Example of a command definition in `definitions.ts`, specifying the command ID, scope, and default keybinding. This serves as the single source of truth for command properties.
```typescript
{ id: 'topic.create', scope: 'renderer', keybinding: { defaultBinding: ['CommandOrControl','N'] } }
```
--------------------------------
### OpenAI Family Emitter Example
Source: https://github.com/cherryhq/cherry-studio/blob/main/docs/references/ai/image-generation-parameters.md
Example of how the 'openaiFamily' emitter handles parameters like quality, background, moderation, and style, keyed under both 'openai' and the raw provider ID.
```typescript
// openai / azure / newapi / cherryin … → { quality, background, moderation, style } dual-keyed under openai + the raw id.
```
--------------------------------
### Manual Version Strategy Example
Source: https://github.com/cherryhq/cherry-studio/blob/main/docs/references/data/database-seeding-guide.md
Assigns a hardcoded string as the version. Use as a last resort and remember to manually bump the version when data changes.
```typescript
readonly version = '1'
```
--------------------------------
### Telegram Adapter Configuration Example
Source: https://github.com/cherryhq/cherry-studio/blob/main/docs/references/cherryclaw/channels.md
Example configuration object for a Telegram channel. It specifies the channel type, ID, enablement status, notification settings, and bot token.
```typescript
{
type: 'telegram',
id: 'unique-channel-id',
enabled: true,
is_notify_receiver: true,
config: {
bot_token: 'YOUR_BOT_TOKEN',
allowed_chat_ids: ['123456789']
}
}
```
--------------------------------
### Fetch Page Content Examples
Source: https://github.com/cherryhq/cherry-studio/blob/main/src/main/ai/mcp/servers/browser/README.md
Demonstrates using the 'open' tool to retrieve page content in different formats like markdown or raw HTML.
```typescript
await open({ url: 'https://example.com', format: 'markdown' })
```
```typescript
await open({ url: 'https://example.com', format: 'html' })
```
--------------------------------
### Bootstrap Phase Execution Flow
Source: https://github.com/cherryhq/cherry-studio/blob/main/docs/references/lifecycle/lifecycle-overview.md
Step-by-step illustration of how the different bootstrap phases are executed and when key lifecycle events occur.
```text
1 Background starts (fire-and-forget) ──────────────────────────────────┐
2 BeforeReady starts ──────────┐ │
2 app.whenReady() ─────────────┤ │
├─ both complete │
▼ │
3 WhenReady starts ────────────┐ │
├─ complete → isBootstrapped = true │
▼ │
4 await Background ◄────────────────────────────────────────────────────┘
5 onAllReady() called on ALL services
→ ALL_SERVICES_READY emitted
```
--------------------------------
### API Operation Examples: Dedicated Endpoints
Source: https://github.com/cherryhq/cherry-studio/blob/main/docs/references/data/api-design-guidelines.md
Examples demonstrating the use of noun-based sub-resources for high-frequency operations or operations with complex side effects, using PUT and POST appropriately.
```typescript
// ✅ Good: Noun-based sub-resource for high-frequency operation
PUT /topics/:id/active-node
{ nodeId: string }
```
```typescript
// ✅ Good: POST for resource creation
POST /messages/:id/duplicate
{ includeDescendants?: boolean }
```
--------------------------------
### Basic useQuery for GET Requests
Source: https://github.com/cherryhq/cherry-studio/blob/main/docs/references/data/data-api-in-renderer.md
Fetch data using useQuery for GET requests. It supports automatic caching and revalidation via SWR. Basic usage involves providing the endpoint.
```typescript
import { useQuery } from '@data/hooks/useDataApi'
// Basic usage
const { data, isLoading, error } = useQuery('/topics')
```
--------------------------------
### Multi-model Request Preparation
Source: https://github.com/cherryhq/cherry-studio/blob/main/docs/references/ai/stream-manager.md
Illustrates the preparation steps for a dispatch when a user mentions multiple models. It shows the resolution of models, creation of placeholders, and building of listeners and model configurations.
```text
User: "Explain quantum mechanics" @gpt-4o @claude-sonnet
↓
PersistentChatContextProvider.prepareDispatch
├─ persist user message (tree node)
├─ resolveModels → [gpt-4o, claude-sonnet]
├─ siblingsGroupId = (monotonic counter)
├─ create one pending assistant placeholder per model (SQLite)
├─ build listeners: subscriber + 2 PersistenceListener (one per backend)
├─ build models: 2 × { modelId, request, rootSpan }
└─ return PreparedDispatch
```
--------------------------------
### Import and Use UI Components
Source: https://github.com/cherryhq/cherry-studio/blob/main/packages/ui/docs/migration-plan.md
Demonstrates how to import and utilize Spinner, DividerWithText, and InfoTooltip components from the @cherrystudio/ui package.
```typescript
import { Spinner, DividerWithText, InfoTooltip } from '@cherrystudio/ui'
function MyComponent() {
return (
)
}
```
--------------------------------
### API Error Response Examples
Source: https://github.com/cherryhq/cherry-studio/blob/main/docs/references/data/api-design-guidelines.md
Illustrates common API error responses, including 404 Not Found, 422 Validation Error, 504 Timeout, and 400 Invalid Operation. These examples show the structure and typical content of the 'details' field for each error type.
```typescript
// 404 Not Found
{
code: 'NOT_FOUND',
message: "Topic with id 'abc123' not found",
status: 404,
details: { resource: 'Topic', id: 'abc123' },
requestContext: { requestId: 'req_123', path: '/topics/abc123', method: 'GET' }
}
```
```typescript
// 422 Validation Error
{
code: 'VALIDATION_ERROR',
message: 'Request validation failed',
status: 422,
details: {
fieldErrors: {
name: ['Name is required', 'Name must be at least 3 characters'],
email: ['Invalid email format']
}
}
}
```
```typescript
// 504 Timeout
{
code: 'TIMEOUT',
message: 'Request timeout: fetch topics (3000ms)',
status: 504,
details: { operation: 'fetch topics', timeoutMs: 3000 }
}
```
```typescript
// 400 Invalid Operation
{
code: 'INVALID_OPERATION',
message: 'Invalid operation: delete root message - cascade=true required',
status: 400,
details: { operation: 'delete root message', reason: 'cascade=true required' }
}
```