diff --git a/apps/desktop/main/ipc/types.ts b/apps/desktop/main/ipc/types.ts index 6e4d3b91..acb0219c 100644 --- a/apps/desktop/main/ipc/types.ts +++ b/apps/desktop/main/ipc/types.ts @@ -11,8 +11,3 @@ export interface IpcContext { /** 主窗口 */ win: BrowserWindow } - -/** - * IPC 处理器注册函数类型 - */ -export type IpcHandlerRegister = (ctx: IpcContext) => void diff --git a/apps/desktop/main/paths/legacy-migration.ts b/apps/desktop/main/paths/legacy-migration.ts index 7e24d105..a59ee832 100644 --- a/apps/desktop/main/paths/legacy-migration.ts +++ b/apps/desktop/main/paths/legacy-migration.ts @@ -7,7 +7,6 @@ import * as fs from 'node:fs' import * as path from 'node:path' import { loadConfig, writeConfigField } from '@openchatlab/config' import { arePathsOverlapping, copyDirMerge, copyDirRecursive, writeMigrationLog } from '../utils/pathUtils' -import { shouldMarkUnifiedDirMigrationDone } from '../utils/unifiedDirMigration' import { ensureDir, getDefaultUserDataDir, @@ -363,7 +362,7 @@ export function migrateToUnifiedDirs(): { success: boolean; error?: string } { writeMigrationLog(getLogsDir(), summary, ensureDir) console.log(`[Migration] ${summary}`) - if (shouldMarkUnifiedDirMigrationDone(failedDirs)) { + if (failedDirs.length === 0) { writeConfigField('data', 'electron_migration_done', true) } diff --git a/apps/desktop/main/utils/unifiedDirMigration.test.ts b/apps/desktop/main/utils/unifiedDirMigration.test.ts deleted file mode 100644 index da71cd82..00000000 --- a/apps/desktop/main/utils/unifiedDirMigration.test.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { describe, it } from 'node:test' -import assert from 'node:assert/strict' -import { shouldMarkUnifiedDirMigrationDone } from './unifiedDirMigration' - -describe('desktop unified directory migration', () => { - it('marks migration done only when no directory failed', () => { - assert.equal(shouldMarkUnifiedDirMigrationDone([]), true) - assert.equal(shouldMarkUnifiedDirMigrationDone(['settings']), false) - }) -}) diff --git a/apps/desktop/main/utils/unifiedDirMigration.ts b/apps/desktop/main/utils/unifiedDirMigration.ts deleted file mode 100644 index 91274fd8..00000000 --- a/apps/desktop/main/utils/unifiedDirMigration.ts +++ /dev/null @@ -1,3 +0,0 @@ -export function shouldMarkUnifiedDirMigrationDone(failedDirs: string[]): boolean { - return failedDirs.length === 0 -} diff --git a/packages/node-runtime/src/import/index.ts b/packages/node-runtime/src/import/index.ts index cdabde8b..da65c4d9 100644 --- a/packages/node-runtime/src/import/index.ts +++ b/packages/node-runtime/src/import/index.ts @@ -1,5 +1,5 @@ -export { writeParseResultToDb } from './write-parse-result' -export type { ImportMeta, WriteParseResultStats } from './write-parse-result' +export { writeParseResultToDb } from '@openchatlab/core' +export type { ImportMeta, WriteParseResultStats } from '@openchatlab/core' export { logNativeParserStatus } from './native-parser-status' export { LogLevel, diff --git a/packages/node-runtime/src/import/write-parse-result.ts b/packages/node-runtime/src/import/write-parse-result.ts deleted file mode 100644 index 06a208b9..00000000 --- a/packages/node-runtime/src/import/write-parse-result.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { writeParseResultToDb } from '@openchatlab/core' -export type { ImportMeta, WriteParseResultStats } from '@openchatlab/core' diff --git a/src/components/common/ChatRecord/BatchSummaryModal.vue b/src/components/common/ChatRecord/BatchSummaryModal.vue index 4bad7f4b..7defed1e 100644 --- a/src/components/common/ChatRecord/BatchSummaryModal.vue +++ b/src/components/common/ChatRecord/BatchSummaryModal.vue @@ -4,7 +4,6 @@ import { useI18n } from 'vue-i18n' import { useDebounceFn } from '@vueuse/core' import { useSessionIndexService } from '@/services' import { getSummaryStrategy } from '@/composables/useUiConfig' -import { stopBatchSummaryGeneration } from './summaryGeneration' const props = defineProps<{ open: boolean @@ -333,7 +332,7 @@ async function startGenerate() { // 停止生成:保持生成锁定,等待当前循环进入 finally 后统一释放。 function stopGenerate() { - stopBatchSummaryGeneration(shouldStop) + shouldStop.value = true } // 关闭弹窗 diff --git a/src/components/common/ChatRecord/SessionTimeline.vue b/src/components/common/ChatRecord/SessionTimeline.vue index 63287a8f..1a0e30ea 100644 --- a/src/components/common/ChatRecord/SessionTimeline.vue +++ b/src/components/common/ChatRecord/SessionTimeline.vue @@ -10,7 +10,6 @@ import { useVirtualizer } from '@tanstack/vue-virtual' import { useSessionIndexService, type ChatSessionItem } from '@/services' import { getSummaryStrategy } from '@/composables/useUiConfig' import BatchSummaryModal from './BatchSummaryModal.vue' -import { buildGenerateSummaryArgs } from './summaryGeneration' // 扁平化列表项类型 type FlatListItem = @@ -257,7 +256,11 @@ async function generateSummary(session: ChatSessionItem, event: Event) { try { console.log('[SessionTimeline] 调用 IPC...') const result = await useSessionIndexService().generateSummary( - ...buildGenerateSummaryArgs(props.sessionId, session.id, locale.value, getSummaryStrategy()) + props.sessionId, + session.id, + locale.value, + false, + getSummaryStrategy() ) console.log('[SessionTimeline] IPC 返回:', result) diff --git a/src/components/common/ChatRecord/summaryGeneration.test.ts b/src/components/common/ChatRecord/summaryGeneration.test.ts deleted file mode 100644 index 746cae99..00000000 --- a/src/components/common/ChatRecord/summaryGeneration.test.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { describe, it } from 'node:test' -import assert from 'node:assert/strict' -import { buildGenerateSummaryArgs } from './summaryGeneration' - -describe('buildGenerateSummaryArgs', () => { - it('passes summary strategy to single-session generation', () => { - const args = buildGenerateSummaryArgs('db-1', 12, 'zh-CN', 'brief') - - assert.deepEqual(args, ['db-1', 12, 'zh-CN', false, 'brief']) - }) -}) diff --git a/src/components/common/ChatRecord/summaryGeneration.ts b/src/components/common/ChatRecord/summaryGeneration.ts deleted file mode 100644 index e8e49db9..00000000 --- a/src/components/common/ChatRecord/summaryGeneration.ts +++ /dev/null @@ -1,18 +0,0 @@ -import type { SummaryStrategy } from '@/composables/useUiConfig' - -export interface MutableBooleanRef { - value: boolean -} - -export function stopBatchSummaryGeneration(shouldStop: MutableBooleanRef): void { - shouldStop.value = true -} - -export function buildGenerateSummaryArgs( - dbSessionId: string, - segmentId: number, - locale: string, - strategy: SummaryStrategy -): [string, number, string, false, SummaryStrategy] { - return [dbSessionId, segmentId, locale, false, strategy] -} diff --git a/src/components/common/Sidebar.vue b/src/components/common/Sidebar.vue index 4feef31f..ddf0d7db 100644 --- a/src/components/common/Sidebar.vue +++ b/src/components/common/Sidebar.vue @@ -24,7 +24,10 @@ import { useLayoutStore } from '@/stores/layout' import { usePlatformService } from '@/services' import { IS_ELECTRON } from '@/utils/platform' import logoSvg from '@/assets/images/logo.svg' -import { focusExposedInput, type ExposedInputRef } from './sidebar/input-focus' + +interface SidebarInputExpose { + inputRef: Pick | null +} const props = withDefaults( defineProps<{ @@ -71,7 +74,7 @@ const isInsightPage = computed(() => String(route.name ?? '').startsWith('insigh const showRenameModal = ref(false) const renameTarget = ref(null) const newName = ref('') -const renameInputRef = ref(null) +const renameInputRef = ref(null) // 删除确认相关状态 const showDeleteModal = ref(false) @@ -297,7 +300,8 @@ function openRenameModal(session: AnalysisSession) { showRenameModal.value = true // 等待 DOM 更新后聚焦输入框 nextTick(() => { - focusExposedInput(renameInputRef.value, { select: true }) + renameInputRef.value?.inputRef?.focus() + renameInputRef.value?.inputRef?.select() }) } diff --git a/src/components/common/sidebar/input-focus.test.ts b/src/components/common/sidebar/input-focus.test.ts deleted file mode 100644 index 2489018d..00000000 --- a/src/components/common/sidebar/input-focus.test.ts +++ /dev/null @@ -1,26 +0,0 @@ -import assert from 'node:assert/strict' -import test from 'node:test' -import { focusExposedInput } from './input-focus' - -test('focuses and selects the native input exposed by UInput', () => { - const calls: string[] = [] - - assert.equal( - focusExposedInput( - { - inputRef: { - focus: () => calls.push('focus'), - select: () => calls.push('select'), - }, - }, - { select: true } - ), - true - ) - assert.deepEqual(calls, ['focus', 'select']) -}) - -test('does nothing before the native input is mounted', () => { - assert.equal(focusExposedInput(null), false) - assert.equal(focusExposedInput({ inputRef: null }), false) -}) diff --git a/src/components/common/sidebar/input-focus.ts b/src/components/common/sidebar/input-focus.ts deleted file mode 100644 index 89e01928..00000000 --- a/src/components/common/sidebar/input-focus.ts +++ /dev/null @@ -1,12 +0,0 @@ -export interface ExposedInputRef { - inputRef: Pick | null -} - -export function focusExposedInput(component: ExposedInputRef | null, options: { select?: boolean } = {}): boolean { - const input = component?.inputRef - if (!input) return false - - input.focus() - if (options.select) input.select() - return true -} diff --git a/src/pages/people/relationships/relationship-galaxy-node-display.ts b/src/pages/people/relationships/relationship-galaxy-node-display.ts index f6d01d00..dc17368a 100644 --- a/src/pages/people/relationships/relationship-galaxy-node-display.ts +++ b/src/pages/people/relationships/relationship-galaxy-node-display.ts @@ -1,5 +1,5 @@ import type { PeopleRelationshipGraphNode, PeopleRelationshipsSearchResult } from '@openchatlab/shared-types' -import { maskRelationshipGalaxyPrivateText, relationshipGalaxyPrivateAvatarText } from './relationship-galaxy-privacy' +import { maskRelationshipGalaxyPrivateText } from './relationship-galaxy-privacy' type DisplayNode = PeopleRelationshipGraphNode | PeopleRelationshipsSearchResult @@ -22,7 +22,7 @@ export function getRelationshipGalaxyNodeAvatarText( options: RelationshipGalaxyNodeDisplayOptions ): string { if (node.kind === 'owner') return options.ownerLabel - if (options.privacyMode) return relationshipGalaxyPrivateAvatarText() + if (options.privacyMode) return '*' return (node.displayName || node.platformId || '?').slice(0, 1) } diff --git a/src/pages/people/relationships/relationship-galaxy-pixi-layers.ts b/src/pages/people/relationships/relationship-galaxy-pixi-layers.ts index 5173380c..3dad1a8d 100644 --- a/src/pages/people/relationships/relationship-galaxy-pixi-layers.ts +++ b/src/pages/people/relationships/relationship-galaxy-pixi-layers.ts @@ -1,8 +1,8 @@ -export interface PixiRemovableChildrenContainer { +interface PixiRemovableChildrenContainer { removeChildren(): PixiDestroyableChild[] } -export interface PixiDestroyableChild { +interface PixiDestroyableChild { destroy(options?: { children?: boolean }): void } diff --git a/src/pages/people/relationships/relationship-galaxy-privacy.test.ts b/src/pages/people/relationships/relationship-galaxy-privacy.test.ts index 2a36ac1d..acde592a 100644 --- a/src/pages/people/relationships/relationship-galaxy-privacy.test.ts +++ b/src/pages/people/relationships/relationship-galaxy-privacy.test.ts @@ -4,7 +4,7 @@ import assert from 'node:assert/strict' import test from 'node:test' -import { maskRelationshipGalaxyPrivateText, relationshipGalaxyPrivateAvatarText } from './relationship-galaxy-privacy' +import { maskRelationshipGalaxyPrivateText } from './relationship-galaxy-privacy' test('masks Chinese names with two stars and the last Chinese character', () => { assert.equal(maskRelationshipGalaxyPrivateText('张小红'), '**红') @@ -24,7 +24,3 @@ test('masks very short and empty relationship labels without revealing full name assert.equal(maskRelationshipGalaxyPrivateText(''), '*') assert.equal(maskRelationshipGalaxyPrivateText(' '), '*') }) - -test('uses a non-identifying avatar fallback in relationship privacy mode', () => { - assert.equal(relationshipGalaxyPrivateAvatarText(), '*') -}) diff --git a/src/pages/people/relationships/relationship-galaxy-privacy.ts b/src/pages/people/relationships/relationship-galaxy-privacy.ts index 13399d43..17ae0b39 100644 --- a/src/pages/people/relationships/relationship-galaxy-privacy.ts +++ b/src/pages/people/relationships/relationship-galaxy-privacy.ts @@ -12,7 +12,3 @@ export function maskRelationshipGalaxyPrivateText(value: string | null | undefin if (characters.length === 2) return `${characters[0]}***` return `${characters[0]}***${characters.at(-1)}` } - -export function relationshipGalaxyPrivateAvatarText(): string { - return '*' -} diff --git a/src/pages/people/relationships/relationship-galaxy-selection.ts b/src/pages/people/relationships/relationship-galaxy-selection.ts index b3ee4b1b..a787ce2d 100644 --- a/src/pages/people/relationships/relationship-galaxy-selection.ts +++ b/src/pages/people/relationships/relationship-galaxy-selection.ts @@ -1,4 +1,4 @@ -export interface RelationshipGalaxyCanvasSelectionInput { +interface RelationshipGalaxyCanvasSelectionInput { selectedKey: string | null loadingNeighborhoodKey: string | null currentCanvasSelectedKey: string | null diff --git a/tests/chatlab-json-export-roundtrip.test.ts b/tests/chatlab-json-export-roundtrip.test.ts index 6508f1ca..1abd2006 100644 --- a/tests/chatlab-json-export-roundtrip.test.ts +++ b/tests/chatlab-json-export-roundtrip.test.ts @@ -6,11 +6,11 @@ import test from 'node:test' import Database from 'better-sqlite3' import { detectFormat, parseFileSync } from '@openchatlab/parser' import { CHATLAB_FORMAT_VERSION } from '@openchatlab/shared-types' +import { writeParseResultToDb } from '@openchatlab/core' import { CHAT_DB_SCHEMA } from '../packages/core/src/schema/tables' import { BetterSqliteAdapter } from '../packages/node-runtime/src/better-sqlite3-adapter' import { exportWithFormat } from '../packages/node-runtime/src/export/format-exporter' import { streamingImport } from '../packages/node-runtime/src/import/streaming-importer' -import { writeParseResultToDb } from '../packages/node-runtime/src/import/write-parse-result' test('exports JSON as ChatLab format that can be parsed for re-import', async () => { const tempDir = mkdtempSync(join(tmpdir(), 'chatlab-json-export-'))