feat: pin conversations and float their action menus
Persist conversation pins across restarts and show pinned conversations first, including older history. Anchor action menus above the list without shifting neighboring rows, with keyboard dismissal and sidebar-close cleanup. Add schema 36 migration, focused regression coverage, and feature documentation. File-level staging also includes existing workbar styles and browser contract adjustments in shared files. Validation: 145 backend tests and 237 App tests passed; typecheck and lint passed. Full test run timed out with Runtime and Agent package failures; native Electron visual validation remains pending. Release note: 会话菜单新增置顶和取消置顶,重启后仍保留;操作菜单现在悬浮显示,不再挤动下方会话。
This commit is contained in:
@@ -553,6 +553,8 @@ export const conversationSnapshotSchema = z
|
||||
.optional(),
|
||||
branch: conversationBranchSchema.optional(),
|
||||
title: z.string().trim().min(1).max(200),
|
||||
// Absent in older snapshots means unpinned; written only via setPinned.
|
||||
pinned: z.boolean().optional(),
|
||||
updatedAt: z.number().int().nonnegative(),
|
||||
// Main-only live projection. Never part of a saved conversation header.
|
||||
activeRequest: z.object({
|
||||
@@ -583,6 +585,15 @@ export const conversationSearchRequestSchema = z.object({
|
||||
conversationIds: z.array(assistantIdSchema).default([])
|
||||
}).strict()
|
||||
|
||||
export const conversationSetPinnedSchema = z.object({
|
||||
conversationId: assistantIdSchema,
|
||||
pinned: z.boolean()
|
||||
}).strict()
|
||||
|
||||
export type ConversationSetPinnedInput = z.infer<
|
||||
typeof conversationSetPinnedSchema
|
||||
>
|
||||
|
||||
export const conversationSnapshotsSchema = z
|
||||
.array(conversationSnapshotSchema)
|
||||
.max(100)
|
||||
@@ -590,6 +601,7 @@ export const conversationSnapshotsSchema = z
|
||||
export const localConversationHeaderSchema = conversationSnapshotSchema
|
||||
.omit({
|
||||
messages: true,
|
||||
pinned: true,
|
||||
remote: true,
|
||||
activeRequest: true
|
||||
})
|
||||
|
||||
@@ -46,6 +46,7 @@ import {
|
||||
type LiveAgentQuestion,
|
||||
type ConversationAttachment,
|
||||
type ConversationBranchInput,
|
||||
type ConversationSetPinnedInput,
|
||||
type ConversationQueueItem,
|
||||
type ConversationContextCompressionState,
|
||||
type LocalConversationSaveBatch,
|
||||
@@ -1393,6 +1394,7 @@ export const browserLiveStateSchema = z
|
||||
conversationId: conversationIdSchema,
|
||||
tabId: browserTabIdSchema,
|
||||
workbarInstanceId: browserWorkbarInstanceIdSchema.optional(),
|
||||
openerTabId: browserTabIdSchema.optional(),
|
||||
ownerWindowId: z.number().int().nonnegative().optional(),
|
||||
status: browserStatusSchema,
|
||||
sessionActive: z.boolean(),
|
||||
@@ -2059,6 +2061,7 @@ export type DesktopApi = {
|
||||
search: (query: string, conversationIds?: string[]) => Promise<string[]>
|
||||
replace: (conversations: ConversationSnapshot[]) => Promise<void>
|
||||
saveLocal: (batch: LocalConversationSaveBatch) => Promise<void>
|
||||
setPinned: (input: ConversationSetPinnedInput) => Promise<void>
|
||||
branchLocal: (
|
||||
input: ConversationBranchInput
|
||||
) => Promise<ConversationSnapshot>
|
||||
|
||||
@@ -190,6 +190,7 @@ export const ipcChannels = {
|
||||
conversationsSearch: 'conversations:search',
|
||||
conversationsReplace: 'conversations:replace',
|
||||
conversationsSaveLocal: 'conversations:save-local',
|
||||
conversationsSetPinned: 'conversations:set-pinned',
|
||||
conversationsBranchLocal: 'conversations:branch-local',
|
||||
conversationsDeleteLocal: 'conversations:delete-local',
|
||||
conversationsChanged: 'conversations:changed',
|
||||
|
||||
Reference in New Issue
Block a user