fix: use directory-aware client for delete, rename, command, permissions, questions
- sessions.ts: deleteSession looks up session.directory and uses clientFor() instead of bare client, so cross-project deletes hit the right server path - index.tsx: submitRename uses clientForDirectory(session.directory) so renames work for sessions not owned by the active project directory - index.tsx: handleSwitchDirectory calls catalog.load() after a directory switch so agents/commands/providers refresh for the new project - session/[id].tsx: introduce sessionClient (directory-aware) and use it in handlePermissionReply, handleQuestionReply, handleQuestionReject, slash-command send, and the refreshPending bootstrap call; also add 'directory' to useEffect deps - catalog.ts: remove debug console.log
This commit is contained in:
committed by
Dennis V
parent
ce598e2a52
commit
0ef3dd37b6
@@ -18,6 +18,7 @@ import { router, useFocusEffect } from "expo-router"
|
||||
import { Ionicons } from "@expo/vector-icons"
|
||||
import { useSessions } from "../../src/stores/sessions"
|
||||
import { useConnections } from "../../src/stores/connections"
|
||||
import { useCatalog } from "../../src/stores/catalog"
|
||||
import type BottomSheet from "@gorhom/bottom-sheet"
|
||||
import type { Session } from "../../src/lib/sdk"
|
||||
import { DirectorySwitcher } from "../../src/components/chat"
|
||||
@@ -123,6 +124,7 @@ export default function SessionsScreen() {
|
||||
addRecentDirectory,
|
||||
recentDirectories,
|
||||
} = useConnections()
|
||||
const loadCatalog = useCatalog((s) => s.load)
|
||||
const dirSheetRef = useRef<BottomSheet>(null)
|
||||
const [refreshing, setRefreshing] = useState(false)
|
||||
|
||||
@@ -131,8 +133,9 @@ export default function SessionsScreen() {
|
||||
await switchDirectory(dir)
|
||||
loadSessions()
|
||||
refreshProject()
|
||||
loadCatalog()
|
||||
},
|
||||
[switchDirectory, loadSessions, refreshProject],
|
||||
[switchDirectory, loadSessions, refreshProject, loadCatalog],
|
||||
)
|
||||
|
||||
useFocusEffect(
|
||||
@@ -157,12 +160,14 @@ export default function SessionsScreen() {
|
||||
|
||||
const submitRename = useCallback(async () => {
|
||||
const title = renameText.trim()
|
||||
if (!title || !renaming || !client) return
|
||||
await client.session.update(renaming.id, { title })
|
||||
if (!title || !renaming) return
|
||||
const renameClient = renaming.directory ? (clientForDirectory(renaming.directory) ?? client) : client
|
||||
if (!renameClient) return
|
||||
await renameClient.session.update(renaming.id, { title })
|
||||
setRenaming(null)
|
||||
setRenameText("")
|
||||
loadSessions()
|
||||
}, [renaming, renameText, client, loadSessions])
|
||||
}, [renaming, renameText, client, clientForDirectory, loadSessions])
|
||||
|
||||
const handleDelete = useCallback(
|
||||
(session: Session) => {
|
||||
|
||||
@@ -107,7 +107,13 @@ export default function SessionScreen() {
|
||||
const isSending = useSessions((s) => !!(currentSession && s.sending[currentSession.id]))
|
||||
|
||||
const { authenticateForMessage } = useAuth()
|
||||
const { client } = useConnections()
|
||||
const { client, clientForDirectory } = useConnections()
|
||||
|
||||
// Use directory-aware client for sessions that belong to a project other than the active one
|
||||
const sessionClient = useMemo(
|
||||
() => (currentSession?.directory ? (clientForDirectory(currentSession.directory) ?? client) : client),
|
||||
[currentSession?.directory, clientForDirectory, client],
|
||||
)
|
||||
|
||||
// Catalog
|
||||
const catalog = useCatalog()
|
||||
@@ -170,9 +176,11 @@ export default function SessionScreen() {
|
||||
selectSession(id, directory).then(() => {
|
||||
// Re-fetch pending permissions/questions from the server to recover from
|
||||
// missed SSE events or failed optimistic removals
|
||||
if (client) refreshPending(client, id)
|
||||
const connState = useConnections.getState()
|
||||
const c = directory ? (connState.clientForDirectory(directory) ?? connState.client) : connState.client
|
||||
if (c) refreshPending(c, id)
|
||||
})
|
||||
}, [id])
|
||||
}, [id, directory])
|
||||
|
||||
// Sync model chip from latest assistant message
|
||||
useEffect(() => {
|
||||
@@ -320,8 +328,8 @@ export default function SessionScreen() {
|
||||
const [cmdName, ...args] = text.split(" ")
|
||||
const name = cmdName.slice(1)
|
||||
const match = serverCommands.find((c) => c.name === name)
|
||||
if (match && client && currentSession) {
|
||||
client.session
|
||||
if (match && sessionClient && currentSession) {
|
||||
sessionClient.session
|
||||
.command(currentSession.id, {
|
||||
command: name,
|
||||
arguments: args.join(" "),
|
||||
@@ -359,7 +367,7 @@ export default function SessionScreen() {
|
||||
}, [loadingMore])
|
||||
|
||||
const handlePermissionReply = async (requestID: string, reply: "once" | "always" | "reject") => {
|
||||
if (!client || !sessionID) return
|
||||
if (!sessionClient || !sessionID) return
|
||||
// Snapshot for rollback
|
||||
const snapshot = useEvents.getState().permissions[sessionID] || []
|
||||
// Optimistically remove from UI
|
||||
@@ -370,7 +378,7 @@ export default function SessionScreen() {
|
||||
},
|
||||
}))
|
||||
try {
|
||||
await client.permission.reply(requestID, reply)
|
||||
await sessionClient.permission.reply(requestID, reply)
|
||||
} catch (err) {
|
||||
console.error("Permission reply failed:", err)
|
||||
// Restore the prompt so the user can retry
|
||||
@@ -382,7 +390,7 @@ export default function SessionScreen() {
|
||||
}
|
||||
|
||||
const handleQuestionReply = async (requestID: string, answers: string[][]) => {
|
||||
if (!client || !sessionID) return
|
||||
if (!sessionClient || !sessionID) return
|
||||
const snapshot = useEvents.getState().questions[sessionID] || []
|
||||
useEvents.setState((state) => ({
|
||||
questions: {
|
||||
@@ -391,7 +399,7 @@ export default function SessionScreen() {
|
||||
},
|
||||
}))
|
||||
try {
|
||||
await client.question.reply(requestID, answers)
|
||||
await sessionClient.question.reply(requestID, answers)
|
||||
} catch (err) {
|
||||
console.error("Question reply failed:", err)
|
||||
useEvents.setState((state) => ({
|
||||
@@ -402,7 +410,7 @@ export default function SessionScreen() {
|
||||
}
|
||||
|
||||
const handleQuestionReject = async (requestID: string) => {
|
||||
if (!client || !sessionID) return
|
||||
if (!sessionClient || !sessionID) return
|
||||
const snapshot = useEvents.getState().questions[sessionID] || []
|
||||
useEvents.setState((state) => ({
|
||||
questions: {
|
||||
@@ -411,7 +419,7 @@ export default function SessionScreen() {
|
||||
},
|
||||
}))
|
||||
try {
|
||||
await client.question.reject(requestID)
|
||||
await sessionClient.question.reject(requestID)
|
||||
} catch (err) {
|
||||
console.error("Question reject failed:", err)
|
||||
useEvents.setState((state) => ({
|
||||
|
||||
Reference in New Issue
Block a user