mirror of
https://github.com/stablyai/orca.git
synced 2026-09-30 08:03:12 +00:00
fix(mobile): sequence structured hold before subscribe
This commit is contained in:
@@ -254,6 +254,34 @@ describe('useMobileStructuredAgentSession', () => {
|
||||
)
|
||||
})
|
||||
|
||||
it('waits for the structured hold before subscribing', async () => {
|
||||
let resolveHold: (() => void) | null = null
|
||||
sendRequest.mockImplementation((method, params) => {
|
||||
if (method === 'agentSession.hold') {
|
||||
return new Promise((resolve) => {
|
||||
resolveHold = () => resolve(ok({ held: true }))
|
||||
})
|
||||
}
|
||||
return defaultSendRequest(method, params)
|
||||
})
|
||||
|
||||
act(() => {
|
||||
renderer = create(createElement(Harness))
|
||||
})
|
||||
|
||||
await vi.waitFor(() => expect(resolveHold).not.toBeNull())
|
||||
expect(subscribe).not.toHaveBeenCalled()
|
||||
|
||||
await act(async () => resolveHold?.())
|
||||
await vi.waitFor(() =>
|
||||
expect(subscribe).toHaveBeenCalledWith(
|
||||
'agentSession.subscribe',
|
||||
{ sessionId: 'session-1' },
|
||||
expect.any(Function)
|
||||
)
|
||||
)
|
||||
})
|
||||
|
||||
it('sends with the shared structured mutation envelope after the stream fence lands', async () => {
|
||||
act(() => {
|
||||
renderer = create(createElement(Harness))
|
||||
|
||||
@@ -45,31 +45,6 @@ export function useMobileStructuredAgentState(args: {
|
||||
setState((current) => reduceStructuredAgentSession(current, action))
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
if (!client || !sessionId || !enabled) {
|
||||
return
|
||||
}
|
||||
const holderId = structuredAgentSessionHolderId('mobile-chat')
|
||||
const held = callAgentSession(client, 'agentSession.hold', {
|
||||
sessionId,
|
||||
holderId
|
||||
}).catch(() => undefined)
|
||||
return () => {
|
||||
void held.then(() =>
|
||||
callAgentSession(
|
||||
client,
|
||||
'agentSession.release',
|
||||
{
|
||||
sessionId,
|
||||
holderId
|
||||
},
|
||||
undefined,
|
||||
{ failWhenDisconnected: true }
|
||||
).catch(() => undefined)
|
||||
)
|
||||
}
|
||||
}, [client, enabled, sessionId])
|
||||
|
||||
useEffect(() => {
|
||||
if (!client || !sessionId || !enabled) {
|
||||
setState(EMPTY_STRUCTURED_AGENT_SESSION)
|
||||
@@ -77,16 +52,55 @@ export function useMobileStructuredAgentState(args: {
|
||||
return
|
||||
}
|
||||
apply({ type: 'loading' })
|
||||
const unsubscribe = client.subscribe('agentSession.subscribe', { sessionId }, (raw) => {
|
||||
if (typeof raw === 'object' && raw !== null && (raw as { type?: unknown }).type === 'error') {
|
||||
apply({ type: 'error', message: String((raw as { message?: unknown }).message ?? '') })
|
||||
return
|
||||
}
|
||||
if (isSubscribeEvent(raw)) {
|
||||
apply({ type: 'event', event: raw })
|
||||
}
|
||||
const holderId = structuredAgentSessionHolderId('mobile-chat')
|
||||
let cancelled = false
|
||||
let unsubscribe = (): void => {}
|
||||
const held = callAgentSession(client, 'agentSession.hold', {
|
||||
sessionId,
|
||||
holderId
|
||||
})
|
||||
return unsubscribe
|
||||
void held
|
||||
.then(() => {
|
||||
if (cancelled) {
|
||||
return
|
||||
}
|
||||
unsubscribe = client.subscribe('agentSession.subscribe', { sessionId }, (raw) => {
|
||||
if (
|
||||
typeof raw === 'object' &&
|
||||
raw !== null &&
|
||||
(raw as { type?: unknown }).type === 'error'
|
||||
) {
|
||||
apply({ type: 'error', message: String((raw as { message?: unknown }).message ?? '') })
|
||||
return
|
||||
}
|
||||
if (isSubscribeEvent(raw)) {
|
||||
apply({ type: 'event', event: raw })
|
||||
}
|
||||
})
|
||||
})
|
||||
.catch((error: unknown) => {
|
||||
if (!cancelled) {
|
||||
apply({ type: 'error', message: error instanceof Error ? error.message : String(error) })
|
||||
}
|
||||
})
|
||||
return () => {
|
||||
cancelled = true
|
||||
unsubscribe()
|
||||
void held
|
||||
.then(() =>
|
||||
callAgentSession(
|
||||
client,
|
||||
'agentSession.release',
|
||||
{
|
||||
sessionId,
|
||||
holderId
|
||||
},
|
||||
undefined,
|
||||
{ failWhenDisconnected: true }
|
||||
).catch(() => undefined)
|
||||
)
|
||||
.catch(() => undefined)
|
||||
}
|
||||
}, [apply, client, enabled, sessionId])
|
||||
|
||||
const loadEarlier = useCallback(() => {
|
||||
|
||||
Reference in New Issue
Block a user