之前是会话tab激活的会话不被空闲回收,现在改为会话tab所有的会话都不被空闲回收
This commit is contained in:
@@ -1,6 +1,13 @@
|
||||
"use client"
|
||||
|
||||
import { Suspense, useCallback, useEffect, useRef, useState } from "react"
|
||||
import {
|
||||
Suspense,
|
||||
useMemo,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useRef,
|
||||
useState,
|
||||
} from "react"
|
||||
import { useSearchParams } from "next/navigation"
|
||||
import type { ImperativePanelGroupHandle } from "react-resizable-panels"
|
||||
import { FolderTitleBar } from "@/components/layout/folder-title-bar"
|
||||
@@ -9,9 +16,12 @@ import { StatusBar } from "@/components/layout/status-bar"
|
||||
import { FolderProvider } from "@/contexts/folder-context"
|
||||
import { TaskProvider } from "@/contexts/task-context"
|
||||
import { AlertProvider } from "@/contexts/alert-context"
|
||||
import { AcpConnectionsProvider } from "@/contexts/acp-connections-context"
|
||||
import {
|
||||
AcpConnectionsProvider,
|
||||
useAcpActions,
|
||||
} from "@/contexts/acp-connections-context"
|
||||
import { ConversationRuntimeProvider } from "@/contexts/conversation-runtime-context"
|
||||
import { TabProvider } from "@/contexts/tab-context"
|
||||
import { TabProvider, useTabContext } from "@/contexts/tab-context"
|
||||
import { SessionStatsProvider } from "@/contexts/session-stats-context"
|
||||
import { SidebarProvider, useSidebarContext } from "@/contexts/sidebar-context"
|
||||
import {
|
||||
@@ -58,6 +68,17 @@ const MIN_CENTER_WIDTH_PX = 420
|
||||
const MIN_WORKSPACE_HEIGHT_PX = 220
|
||||
const LAYOUT_EPSILON = 0.25
|
||||
|
||||
/** Syncs open tab keys from TabProvider to AcpConnectionsProvider */
|
||||
function TabKeysSync() {
|
||||
const { tabs } = useTabContext()
|
||||
const { registerOpenTabKeys } = useAcpActions()
|
||||
const keys = useMemo(() => new Set(tabs.map((t) => t.id)), [tabs])
|
||||
useEffect(() => {
|
||||
registerOpenTabKeys(keys)
|
||||
}, [keys, registerOpenTabKeys])
|
||||
return null
|
||||
}
|
||||
|
||||
function isSameLayout(a: number[], b: number[]): boolean {
|
||||
if (a.length !== b.length) return false
|
||||
return a.every((value, index) => Math.abs(value - b[index]) <= LAYOUT_EPSILON)
|
||||
@@ -649,6 +670,7 @@ function FolderLayoutInner({ children }: { children: React.ReactNode }) {
|
||||
<ConversationRuntimeProvider>
|
||||
<WorkspaceProvider key={`workspace-${normalizedFolderId}`}>
|
||||
<TabProvider>
|
||||
<TabKeysSync />
|
||||
<SessionStatsProvider>
|
||||
<SidebarProvider
|
||||
key={`left-sidebar-${normalizedFolderId}`}
|
||||
|
||||
@@ -1082,6 +1082,7 @@ export interface AcpActionsValue {
|
||||
): Promise<void>
|
||||
setActiveKey(key: string | null): void
|
||||
touchActivity(contextKey: string): void
|
||||
registerOpenTabKeys(keys: Set<string>): void
|
||||
}
|
||||
|
||||
const AcpActionsContext = createContext<AcpActionsValue | null>(null)
|
||||
@@ -1147,6 +1148,9 @@ export function AcpConnectionsProvider({ children }: { children: ReactNode }) {
|
||||
// connectionId → contextKey reverse mapping
|
||||
const reverseMapRef = useRef(new Map<string, string>())
|
||||
|
||||
// Open tab keys — updated by child TabProvider via registerOpenTabKeys
|
||||
const openTabKeysRef = useRef(new Set<string>())
|
||||
|
||||
// Guard against concurrent connect() calls
|
||||
const connectingKeysRef = useRef(new Set<string>())
|
||||
// Keys whose disconnect was requested while connect was still in flight
|
||||
@@ -1309,6 +1313,10 @@ export function AcpConnectionsProvider({ children }: { children: ReactNode }) {
|
||||
lastActivityRef.current.set(contextKey, Date.now())
|
||||
}, [])
|
||||
|
||||
const registerOpenTabKeys = useCallback((keys: Set<string>) => {
|
||||
openTabKeysRef.current = keys
|
||||
}, [])
|
||||
|
||||
const flushStreamingQueue = useCallback(() => {
|
||||
flushTimerRef.current = null
|
||||
const queued = streamingQueueRef.current
|
||||
@@ -1649,9 +1657,11 @@ export function AcpConnectionsProvider({ children }: { children: ReactNode }) {
|
||||
const now = Date.now()
|
||||
const currentActiveKey = storeRef.current.activeKey
|
||||
|
||||
const currentOpenTabKeys = openTabKeysRef.current
|
||||
const toDisconnect: { contextKey: string; connectionId: string }[] = []
|
||||
for (const [contextKey, conn] of storeRef.current.connections) {
|
||||
if (contextKey === currentActiveKey) continue
|
||||
if (currentOpenTabKeys.has(contextKey)) continue
|
||||
if (
|
||||
conn.status === "prompting" ||
|
||||
conn.status === "connecting" ||
|
||||
@@ -1923,6 +1933,7 @@ export function AcpConnectionsProvider({ children }: { children: ReactNode }) {
|
||||
respondPermission,
|
||||
setActiveKey,
|
||||
touchActivity,
|
||||
registerOpenTabKeys,
|
||||
}),
|
||||
[
|
||||
connect,
|
||||
@@ -1935,6 +1946,7 @@ export function AcpConnectionsProvider({ children }: { children: ReactNode }) {
|
||||
respondPermission,
|
||||
setActiveKey,
|
||||
touchActivity,
|
||||
registerOpenTabKeys,
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user