Skip to content

Commit 299a1ef

Browse files
committed
fix(extension): send and stop an opened workspace chat under its own workspace
The organization conversation mounted useChat with the organization scope for every chat, so a workspace chat opened from the organization's list was refused (send 404, Stop forbidden). It now reads the scope from the chat's history, the same read useChat makes, and nothing sends on an existing chat until that history lands. A new chat stays the organization's.
1 parent 51ef2c0 commit 299a1ef

1 file changed

Lines changed: 39 additions & 23 deletions

File tree

‎apps/sim/app/_organization-conversation/use-organization-conversation.ts‎

Lines changed: 39 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,10 @@ import {
4545
useResourcePanelController,
4646
} from '@/hooks/mothership-chat/use-resource-panel'
4747
import { useRestoredChatEntry } from '@/hooks/mothership-chat/use-restored-chat-entry'
48-
import { useMarkMothershipChatRead } from '@/hooks/queries/mothership-chats'
48+
import {
49+
useMarkMothershipChatRead,
50+
useMothershipChatHistory,
51+
} from '@/hooks/queries/mothership-chats'
4952
import { useSearchHistoryActions } from '@/hooks/sim-search/source-history'
5053
import { type PrepareChatSubmission, useComposerSubmission } from '@/hooks/use-composer-submission'
5154
import { useHydrated } from '@/hooks/use-hydrated'
@@ -159,25 +162,36 @@ export function useOrganizationConversation({
159162
)
160163
const controller = useResourcePanelController()
161164
const queryClient = useQueryClient()
162-
const chat = useChat({ organizationId: organization.id }, chatId, {
163-
...getMothershipUseChatOptions({
164-
requestMode,
165-
getChatUrl:
166-
destinationMode === 'assistant'
167-
? (id) =>
168-
serializeSearchConversation(organizationRoutes(organization.id).searchChat(id), {
169-
...searchParams,
170-
mode: active ? 'assistant' : 'search',
171-
resource: controller.activeResourceState[0],
172-
})
173-
: undefined,
174-
onResourceEvent: controller.onResourceEvent,
175-
activeResourceState: controller.activeResourceState,
176-
}),
177-
...(panelSurface
178-
? { projectsDesktopTabs: false, onChatIdResolved: panelSurface.onChatIdResolved }
179-
: {}),
180-
})
165+
/**
166+
* The organization's list holds the viewer's workspace chats too, and the server admits a send or
167+
* Stop only under the scope a chat was created in. An existing chat's scope comes from its history
168+
* (the read `useChat` makes), and nothing sends before it lands; a new chat is the organization's.
169+
*/
170+
const { data: openedHistory } = useMothershipChatHistory(chatId)
171+
const scopeKnown = !chatId || openedHistory !== undefined
172+
const chat = useChat(
173+
{ organizationId: organization.id, workspaceId: openedHistory?.workspaceId ?? undefined },
174+
chatId,
175+
{
176+
...getMothershipUseChatOptions({
177+
requestMode,
178+
getChatUrl:
179+
destinationMode === 'assistant'
180+
? (id) =>
181+
serializeSearchConversation(organizationRoutes(organization.id).searchChat(id), {
182+
...searchParams,
183+
mode: active ? 'assistant' : 'search',
184+
resource: controller.activeResourceState[0],
185+
})
186+
: undefined,
187+
onResourceEvent: controller.onResourceEvent,
188+
activeResourceState: controller.activeResourceState,
189+
}),
190+
...(panelSurface
191+
? { projectsDesktopTabs: false, onChatIdResolved: panelSurface.onChatIdResolved }
192+
: {}),
193+
}
194+
)
181195
const newDraftSlot =
182196
surface.kind === 'panel'
183197
? 'home'
@@ -291,7 +305,8 @@ export function useOrganizationConversation({
291305

292306
const consumedSummary = useRef<string | null>(null)
293307
useEffect(() => {
294-
if (!active || !summaryRequest || consumedSummary.current === summaryRequest.id) return
308+
if (!active || !scopeKnown || !summaryRequest || consumedSummary.current === summaryRequest.id)
309+
return
295310
consumedSummary.current = summaryRequest.id
296311
onSummaryConsumed?.(summaryRequest.id)
297312
void sendMessage(
@@ -300,14 +315,15 @@ export function useOrganizationConversation({
300315
undefined,
301316
chatSendOptions('assistant', summaryRequest.assistantSearch)
302317
)
303-
}, [active, summaryRequest, onSummaryConsumed, sendMessage])
318+
}, [active, scopeKnown, summaryRequest, onSummaryConsumed, sendMessage])
304319

305320
const send = (
306321
message: string,
307322
fileAttachments?: FileAttachmentForApi[],
308323
contexts?: ChatContext[],
309324
assistantSearch?: WorkspaceSearchFilters
310325
) => {
326+
if (!scopeKnown) return
311327
if (requestMode === 'assistant') recordQuery(message)
312328
if (requestMode !== 'assistant' && !panelSurface) panel.prepareResourceViewForAgentTurn()
313329
void sendMessage(
@@ -318,7 +334,7 @@ export function useOrganizationConversation({
318334
)
319335
}
320336
const submit = (text: string, contexts?: ChatContext[]) => {
321-
if (files.attachedFiles.some((file) => file.uploading)) return false
337+
if (!scopeKnown || files.attachedFiles.some((file) => file.uploading)) return false
322338
if (requestMode === 'assistant') {
323339
if (files.attachedFiles.some((file) => !isAssistantImageType(file.type))) {
324340
toast.error('Remove unsupported files to use Assistant.')

0 commit comments

Comments
 (0)