mirror of
https://github.com/stablyai/orca.git
synced 2026-10-08 00:02:38 +00:00
fix(mobile): show a message the host recorded and then rejected in place, as on the desktop
Design case 1: the phone no longer hands such a message back or banners it (this branch's earlier change), so its row is where it lives; the phone now draws it as not sent, like the desktop, and leaves one a queued card holds to that card.
This commit is contained in:
@@ -5,6 +5,7 @@ import type { AgentJournalDispatchState } from '../../../src/shared/agent-sessio
|
||||
import type { AgentSessionSubscribeEvent } from '../../../src/shared/agent-session-wire'
|
||||
import type { RpcClient } from '../transport/rpc-client'
|
||||
import { markRpcDeliveryUnknown } from '../transport/rpc-delivery-ambiguity'
|
||||
import { agentJournalSubmissionKey } from '../../../src/shared/agent-session-journal-item-key'
|
||||
import { resetMobileStructuredSendOperationJournalForTests } from './mobile-structured-send-operation-journal'
|
||||
import { structuredSendResultFixture } from './structured-agent-send-result.test-fixture'
|
||||
import { useMobileStructuredAgentSession } from './use-mobile-structured-agent-session'
|
||||
@@ -257,6 +258,43 @@ describe('mobile structured send retries', () => {
|
||||
expect(calls().every(([, params]) => !('retryUnknown' in (params as object)))).toBe(true)
|
||||
})
|
||||
|
||||
// The host's row is where a recorded, rejected message lives on the phone, as on the desktop.
|
||||
it('shows a message the host recorded and then rejected as not sent, in place', async () => {
|
||||
await mountSession()
|
||||
const event = snapshotEvent()
|
||||
const itemId = agentJournalSubmissionKey('rejected-1')
|
||||
act(() =>
|
||||
listener?.({
|
||||
...event,
|
||||
page: {
|
||||
...event.page,
|
||||
items: [
|
||||
{
|
||||
itemId,
|
||||
revision: 1,
|
||||
sequence: 1,
|
||||
observedAt: 10,
|
||||
body: { kind: 'message', role: 'user', blocks: [{ type: 'text', text: 'lost' }] }
|
||||
}
|
||||
],
|
||||
submissions: [
|
||||
{
|
||||
clientMessageId: 'rejected-1',
|
||||
fence: 3,
|
||||
payloadFingerprint: 'fingerprint',
|
||||
dispatchState: 'rejected',
|
||||
providerItemId: null,
|
||||
reason: 'provider_write_failed: broken pipe',
|
||||
submittedAt: 10,
|
||||
resolvedAt: 10
|
||||
}
|
||||
]
|
||||
}
|
||||
})
|
||||
)
|
||||
expect(hook!.session.messages).toEqual([expect.objectContaining({ id: itemId, unsent: true })])
|
||||
})
|
||||
|
||||
// The transcript owns a message the host recorded, so the composer never gets it back.
|
||||
it('hands back only a send a Stop withdrew, never one the host recorded and rejected', async () => {
|
||||
let reason = 'provider_write_failed: broken pipe'
|
||||
|
||||
@@ -157,13 +157,18 @@ export function useMobileStructuredAgentSession(args: {
|
||||
onSendError
|
||||
})
|
||||
|
||||
const queuedMessageIds = useMemo(
|
||||
() => (queuedMessages ?? []).map((message) => message.messageId),
|
||||
[queuedMessages]
|
||||
)
|
||||
const messages = useMemo(
|
||||
// Off: the phone hands a rejected message back to its composer, so a row would show it twice.
|
||||
// As on the desktop: a message the host recorded lives on its row, never back in the composer.
|
||||
() =>
|
||||
projectStructuredAgentSessionMessages(state.items, [], state.submissions, {
|
||||
rejectedInPlace: false
|
||||
rejectedInPlace: true,
|
||||
queuedMessageIds
|
||||
}),
|
||||
[state.items, state.submissions]
|
||||
[state.items, state.submissions, queuedMessageIds]
|
||||
)
|
||||
const turnId = activeStructuredAgentSessionTurnId(state.items)
|
||||
const turnTiming = useMobileStructuredAgentTurnTiming(state, turnId)
|
||||
|
||||
Reference in New Issue
Block a user