### 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' } } ```