mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2025-12-19 22:52:08 +08:00
pack optimization
This commit is contained in:
parent
9e4b792fc3
commit
b131f0c48c
@ -35,6 +35,9 @@ const allX64 = {
|
|||||||
'@napi-rs/system-ocr-win32-x64-msvc': '1.0.2'
|
'@napi-rs/system-ocr-win32-x64-msvc': '1.0.2'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const claudeCodeVenderPath = '@anthropic-ai/claude-code/vendor'
|
||||||
|
const claudeCodeVenders = ['arm64-darwin', 'arm64-linux', 'x64-darwin', 'x64-linux', 'x64-win32']
|
||||||
|
|
||||||
const platformToArch = {
|
const platformToArch = {
|
||||||
mac: 'darwin',
|
mac: 'darwin',
|
||||||
windows: 'win32',
|
windows: 'win32',
|
||||||
@ -46,9 +49,6 @@ exports.default = async function (context) {
|
|||||||
const archType = arch === Arch.arm64 ? 'arm64' : 'x64'
|
const archType = arch === Arch.arm64 ? 'arm64' : 'x64'
|
||||||
const platform = context.packager.platform.name
|
const platform = context.packager.platform.name
|
||||||
|
|
||||||
const arm64Filters = Object.keys(allArm64).map((f) => '!node_modules/' + f + '/**')
|
|
||||||
const x64Filters = Object.keys(allX64).map((f) => '!node_modules/' + f + '/*')
|
|
||||||
|
|
||||||
const downloadPackages = async (packages) => {
|
const downloadPackages = async (packages) => {
|
||||||
console.log('downloading packages ......')
|
console.log('downloading packages ......')
|
||||||
const downloadPromises = []
|
const downloadPromises = []
|
||||||
@ -67,25 +67,39 @@ exports.default = async function (context) {
|
|||||||
await Promise.all(downloadPromises)
|
await Promise.all(downloadPromises)
|
||||||
}
|
}
|
||||||
|
|
||||||
const changeFilters = async (packages, filtersToExclude, filtersToInclude) => {
|
const changeFilters = async (filtersToExclude, filtersToInclude) => {
|
||||||
await downloadPackages(packages)
|
|
||||||
// remove filters for the target architecture (allow inclusion)
|
// remove filters for the target architecture (allow inclusion)
|
||||||
|
|
||||||
let filters = context.packager.config.files[0].filter
|
let filters = context.packager.config.files[0].filter
|
||||||
filters = filters.filter((filter) => !filtersToInclude.includes(filter))
|
filters = filters.filter((filter) => !filtersToInclude.includes(filter))
|
||||||
|
|
||||||
// add filters for other architectures (exclude them)
|
// add filters for other architectures (exclude them)
|
||||||
filters.push(...filtersToExclude)
|
filters.push(...filtersToExclude)
|
||||||
|
|
||||||
context.packager.config.files[0].filter = filters
|
context.packager.config.files[0].filter = filters
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arch === Arch.arm64) {
|
await downloadPackages(arch === Arch.arm64 ? allArm64 : allX64)
|
||||||
await changeFilters(allArm64, x64Filters, arm64Filters)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (arch === Arch.x64) {
|
const arm64Filters = Object.keys(allArm64).map((f) => '!node_modules/' + f + '/**')
|
||||||
await changeFilters(allX64, arm64Filters, x64Filters)
|
const x64Filters = Object.keys(allX64).map((f) => '!node_modules/' + f + '/*')
|
||||||
return
|
const excludeClaudeCodeRipgrepFilters = claudeCodeVenders
|
||||||
|
.filter((f) => f !== `${archType}-${platformToArch[platform]}`)
|
||||||
|
.map((f) => '!node_modules/' + claudeCodeVenderPath + '/ripgrep/' + f + '/**')
|
||||||
|
const excludeClaudeCodeJBPlutins = ['!node_modules/' + claudeCodeVenderPath + '/' + 'claude-code-jetbrains-plugin']
|
||||||
|
|
||||||
|
const includeClaudeCodeFilters = [
|
||||||
|
'!node_modules/' + claudeCodeVenderPath + '/' + `${archType}-${platformToArch[platform]}/**`
|
||||||
|
]
|
||||||
|
|
||||||
|
if (arch === Arch.arm64) {
|
||||||
|
await changeFilters(
|
||||||
|
[...x64Filters, ...excludeClaudeCodeRipgrepFilters, ...excludeClaudeCodeJBPlutins],
|
||||||
|
[...arm64Filters, ...includeClaudeCodeFilters]
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
await changeFilters(
|
||||||
|
[...arm64Filters, ...excludeClaudeCodeRipgrepFilters, ...excludeClaudeCodeJBPlutins],
|
||||||
|
[...x64Filters, ...includeClaudeCodeFilters]
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -36,10 +36,7 @@ export const createMessage = async (req: Request, res: Response): Promise<void>
|
|||||||
logger.debug('Streaming message data:', messageData)
|
logger.debug('Streaming message data:', messageData)
|
||||||
|
|
||||||
// Step 1: Save user message first
|
// Step 1: Save user message first
|
||||||
const userMessage = await sessionMessageService.saveUserMessage(
|
const userMessage = await sessionMessageService.saveUserMessage(sessionId, messageData.content)
|
||||||
sessionId,
|
|
||||||
messageData.content
|
|
||||||
)
|
|
||||||
|
|
||||||
// Set SSE headers
|
// Set SSE headers
|
||||||
res.setHeader('Content-Type', 'text/event-stream')
|
res.setHeader('Content-Type', 'text/event-stream')
|
||||||
@ -48,7 +45,6 @@ export const createMessage = async (req: Request, res: Response): Promise<void>
|
|||||||
res.setHeader('Access-Control-Allow-Origin', '*')
|
res.setHeader('Access-Control-Allow-Origin', '*')
|
||||||
res.setHeader('Access-Control-Allow-Headers', 'Cache-Control')
|
res.setHeader('Access-Control-Allow-Headers', 'Cache-Control')
|
||||||
|
|
||||||
|
|
||||||
const messageStream = sessionMessageService.createSessionMessage(session, messageData, userMessage.id)
|
const messageStream = sessionMessageService.createSessionMessage(session, messageData, userMessage.id)
|
||||||
|
|
||||||
// Track stream lifecycle so we keep the SSE connection open until persistence finishes
|
// Track stream lifecycle so we keep the SSE connection open until persistence finishes
|
||||||
|
|||||||
@ -51,9 +51,7 @@ export class MigrationService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get applied migrations
|
// Get applied migrations
|
||||||
const appliedMigrations = hasMigrationsTable
|
const appliedMigrations = hasMigrationsTable ? await this.getAppliedMigrations() : []
|
||||||
? await this.getAppliedMigrations()
|
|
||||||
: []
|
|
||||||
const appliedVersions = new Set(appliedMigrations.map((m) => Number(m.version)))
|
const appliedVersions = new Set(appliedMigrations.map((m) => Number(m.version)))
|
||||||
|
|
||||||
const latestAppliedVersion = appliedMigrations.reduce(
|
const latestAppliedVersion = appliedMigrations.reduce(
|
||||||
@ -90,9 +88,7 @@ export class MigrationService {
|
|||||||
|
|
||||||
private async migrationsTableExists(): Promise<boolean> {
|
private async migrationsTableExists(): Promise<boolean> {
|
||||||
try {
|
try {
|
||||||
const table = await this.client.execute(
|
const table = await this.client.execute(`SELECT name FROM sqlite_master WHERE type='table' AND name='migrations'`)
|
||||||
`SELECT name FROM sqlite_master WHERE type='table' AND name='migrations'`
|
|
||||||
)
|
|
||||||
return table.rows.length > 0
|
return table.rows.length > 0
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error('Failed to check migrations table status:', { error })
|
logger.error('Failed to check migrations table status:', { error })
|
||||||
@ -162,5 +158,4 @@ export class MigrationService {
|
|||||||
throw error
|
throw error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { EventEmitter } from 'node:events'
|
import { EventEmitter } from 'node:events'
|
||||||
|
|
||||||
|
import { PermissionMode } from '@anthropic-ai/claude-code'
|
||||||
import { loggerService } from '@logger'
|
import { loggerService } from '@logger'
|
||||||
import type {
|
import type {
|
||||||
AgentSessionMessageEntity,
|
AgentSessionMessageEntity,
|
||||||
@ -294,8 +295,8 @@ export class SessionMessageService extends BaseService {
|
|||||||
|
|
||||||
// Create the streaming agent invocation (using invokeStream for streaming)
|
// Create the streaming agent invocation (using invokeStream for streaming)
|
||||||
const claudeStream = this.cc.invoke(req.content, session.accessible_paths[0], session_id, {
|
const claudeStream = this.cc.invoke(req.content, session.accessible_paths[0], session_id, {
|
||||||
permissionMode: session.configuration?.permission_mode,
|
permissionMode: (session.configuration?.permissionMode as PermissionMode) || 'default',
|
||||||
maxTurns: session.configuration?.max_turns
|
maxTurns: (session.configuration?.maxTurns as number) || 10
|
||||||
})
|
})
|
||||||
|
|
||||||
// Use chunk accumulator to manage streaming data
|
// Use chunk accumulator to manage streaming data
|
||||||
|
|||||||
@ -11,7 +11,6 @@ import { and, count, eq, type SQL } from 'drizzle-orm'
|
|||||||
import { BaseService } from '../BaseService'
|
import { BaseService } from '../BaseService'
|
||||||
import { agentsTable, type InsertSessionRow, type SessionRow, sessionsTable } from '../database/schema'
|
import { agentsTable, type InsertSessionRow, type SessionRow, sessionsTable } from '../database/schema'
|
||||||
|
|
||||||
|
|
||||||
export class SessionService extends BaseService {
|
export class SessionService extends BaseService {
|
||||||
private static instance: SessionService | null = null
|
private static instance: SessionService | null = null
|
||||||
|
|
||||||
|
|||||||
@ -22,4 +22,5 @@ export type {
|
|||||||
CreateSessionRequest,
|
CreateSessionRequest,
|
||||||
GetAgentSessionResponse,
|
GetAgentSessionResponse,
|
||||||
ListOptions as SessionListOptions,
|
ListOptions as SessionListOptions,
|
||||||
UpdateSessionRequest} from '@types'
|
UpdateSessionRequest
|
||||||
|
} from '@types'
|
||||||
|
|||||||
@ -42,7 +42,7 @@ function ContextMenuSubTrigger({
|
|||||||
data-slot="context-menu-sub-trigger"
|
data-slot="context-menu-sub-trigger"
|
||||||
data-inset={inset}
|
data-inset={inset}
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex cursor-default items-center rounded-sm px-2 py-1.5 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-[inset]:pl-8 data-[state=open]:bg-accent data-[state=open]:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
"flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-hidden focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[inset]:pl-8 data-[state=open]:text-accent-foreground [&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...props}>
|
{...props}>
|
||||||
@ -57,7 +57,7 @@ function ContextMenuSubContent({ className, ...props }: React.ComponentProps<typ
|
|||||||
<ContextMenuPrimitive.SubContent
|
<ContextMenuPrimitive.SubContent
|
||||||
data-slot="context-menu-sub-content"
|
data-slot="context-menu-sub-content"
|
||||||
className={cn(
|
className={cn(
|
||||||
'z-50 min-w-[8rem] origin-(--radix-context-menu-content-transform-origin) overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95',
|
'data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 z-50 min-w-[8rem] origin-(--radix-context-menu-content-transform-origin) overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[state=closed]:animate-out data-[state=open]:animate-in',
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
@ -71,7 +71,7 @@ function ContextMenuContent({ className, ...props }: React.ComponentProps<typeof
|
|||||||
<ContextMenuPrimitive.Content
|
<ContextMenuPrimitive.Content
|
||||||
data-slot="context-menu-content"
|
data-slot="context-menu-content"
|
||||||
className={cn(
|
className={cn(
|
||||||
'z-50 max-h-(--radix-context-menu-content-available-height) min-w-[8rem] origin-(--radix-context-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95',
|
'data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 z-50 max-h-(--radix-context-menu-content-available-height) min-w-[8rem] origin-(--radix-context-menu-content-transform-origin) overflow-y-auto overflow-x-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=closed]:animate-out data-[state=open]:animate-in',
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
@ -95,7 +95,7 @@ function ContextMenuItem({
|
|||||||
data-inset={inset}
|
data-inset={inset}
|
||||||
data-variant={variant}
|
data-variant={variant}
|
||||||
className={cn(
|
className={cn(
|
||||||
"relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:focus:text-destructive dark:data-[variant=destructive]:focus:bg-destructive/20 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground data-[variant=destructive]:*:[svg]:!text-destructive",
|
"data-[variant=destructive]:*:[svg]:!text-destructive relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[inset]:pl-8 data-[variant=destructive]:text-destructive data-[disabled]:opacity-50 data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:focus:text-destructive dark:data-[variant=destructive]:focus:bg-destructive/20 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
@ -113,7 +113,7 @@ function ContextMenuCheckboxItem({
|
|||||||
<ContextMenuPrimitive.CheckboxItem
|
<ContextMenuPrimitive.CheckboxItem
|
||||||
data-slot="context-menu-checkbox-item"
|
data-slot="context-menu-checkbox-item"
|
||||||
className={cn(
|
className={cn(
|
||||||
"relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
"relative flex cursor-default select-none items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
checked={checked}
|
checked={checked}
|
||||||
@ -137,7 +137,7 @@ function ContextMenuRadioItem({
|
|||||||
<ContextMenuPrimitive.RadioItem
|
<ContextMenuPrimitive.RadioItem
|
||||||
data-slot="context-menu-radio-item"
|
data-slot="context-menu-radio-item"
|
||||||
className={cn(
|
className={cn(
|
||||||
"relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
"relative flex cursor-default select-none items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...props}>
|
{...props}>
|
||||||
@ -162,7 +162,7 @@ function ContextMenuLabel({
|
|||||||
<ContextMenuPrimitive.Label
|
<ContextMenuPrimitive.Label
|
||||||
data-slot="context-menu-label"
|
data-slot="context-menu-label"
|
||||||
data-inset={inset}
|
data-inset={inset}
|
||||||
className={cn('px-2 py-1.5 text-sm font-medium text-foreground data-[inset]:pl-8', className)}
|
className={cn('px-2 py-1.5 font-medium text-foreground text-sm data-[inset]:pl-8', className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
@ -182,7 +182,7 @@ function ContextMenuShortcut({ className, ...props }: React.ComponentProps<'span
|
|||||||
return (
|
return (
|
||||||
<span
|
<span
|
||||||
data-slot="context-menu-shortcut"
|
data-slot="context-menu-shortcut"
|
||||||
className={cn('ml-auto text-xs tracking-widest text-muted-foreground', className)}
|
className={cn('ml-auto text-muted-foreground text-xs tracking-widest', className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user