mirror of
https://github.com/stablyai/orca.git
synced 2026-10-19 16:03:26 +00:00
fix(native-chat): only seed single-line unsubmitted launch drafts
The unsubmitted-delivery branch seeded on every draft delivery, which also caught the agent-session-fork path whose prompt is multi-line scraped context. The chat send pre-clears the TUI with Ctrl+U (kill-to-start-of-LINE), so a multi-line prefill cannot be fully cleared and its earlier lines would glue onto the next message. The GitHub work-item draft this feature targets is a bare issue URL, so narrowing costs it nothing. Also assert the composer retires the seed after a send — deleting that call previously failed no test.
This commit is contained in:
@@ -32,7 +32,9 @@ const mocks = vi.hoisted(() => ({
|
||||
sendNativeChatMessageVerified: vi.fn(),
|
||||
trackPendingSend: vi.fn(),
|
||||
setDraft: vi.fn(),
|
||||
draftScopeKeys: [] as string[]
|
||||
draftScopeKeys: [] as string[],
|
||||
clearNativeChatLaunchDraft: vi.fn(),
|
||||
markNativeChatLaunchDraftAdopted: vi.fn()
|
||||
}))
|
||||
|
||||
vi.mock('../../store', () => {
|
||||
@@ -40,8 +42,8 @@ vi.mock('../../store', () => {
|
||||
dictationState: 'idle',
|
||||
settings: { voice: { enabled: false }, nativeChatSessionOptions: {} },
|
||||
updateSettings: vi.fn(),
|
||||
clearNativeChatLaunchDraft: vi.fn(),
|
||||
markNativeChatLaunchDraftAdopted: vi.fn()
|
||||
clearNativeChatLaunchDraft: mocks.clearNativeChatLaunchDraft,
|
||||
markNativeChatLaunchDraftAdopted: mocks.markNativeChatLaunchDraftAdopted
|
||||
}
|
||||
const useAppStore = (selector: (value: typeof state) => unknown) => selector(state)
|
||||
useAppStore.getState = () => state
|
||||
@@ -203,6 +205,22 @@ describe('NativeChatComposer', () => {
|
||||
expect(mocks.trackPendingSend).toHaveBeenCalledWith(mocks.sendHandle, 'pending-1')
|
||||
})
|
||||
|
||||
it('retires the launch-draft seed once a send clears the TUI input line', () => {
|
||||
render(
|
||||
<NativeChatComposer
|
||||
terminalTabId="tab-1"
|
||||
paneKey="tab-1:leaf-1"
|
||||
targetPtyId="pty-1"
|
||||
agent="codex"
|
||||
/>
|
||||
)
|
||||
expect(mocks.clearNativeChatLaunchDraft).not.toHaveBeenCalled()
|
||||
|
||||
act(() => mocks.fieldProps?.onSend?.())
|
||||
|
||||
expect(mocks.clearNativeChatLaunchDraft).toHaveBeenCalledWith('tab-1')
|
||||
})
|
||||
|
||||
it('keeps the draft scope anchored to the pane while the PTY reconnects', () => {
|
||||
const view = render(
|
||||
<NativeChatComposer
|
||||
|
||||
@@ -101,6 +101,21 @@ describe('deliverLaunchPromptToAgentTab', () => {
|
||||
expect(mocks.seedNativeChatLaunchPrompt).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('does not seed a launch draft for multi-line content', async () => {
|
||||
// The chat send pre-clears the TUI with Ctrl+U (kill-to-start-of-LINE), so a
|
||||
// multi-line prefill (e.g. scraped session-fork context) would leave earlier
|
||||
// lines behind to glue onto the next message.
|
||||
await deliverLaunchPromptToAgentTab({
|
||||
tabId: 'fork-tab',
|
||||
agent: 'codex',
|
||||
content: 'Forked from session\n\nhttps://example.test/context',
|
||||
submit: false,
|
||||
forcePaste: false
|
||||
})
|
||||
|
||||
expect(mocks.seedNativeChatLaunchDraft).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('does not seed a launch draft for submitted, unsupported, or empty content', async () => {
|
||||
await deliverLaunchPromptToAgentTab({
|
||||
tabId: 'submit-tab',
|
||||
|
||||
@@ -43,9 +43,12 @@ export function deliverLaunchPromptToAgentTab(args: {
|
||||
text: content,
|
||||
createdAt: Date.now()
|
||||
})
|
||||
} else if (submit !== true) {
|
||||
} else if (submit !== true && !content.includes('\n')) {
|
||||
// Why: an unsubmitted draft lives only in the TUI input buffer; seed the
|
||||
// chat-composer copy so the context isn't invisible in the GUI view.
|
||||
// Single-line only: the chat send pre-clears the TUI with Ctrl+U
|
||||
// (kill-to-start-of-LINE), so a multi-line prefill (e.g. scraped fork
|
||||
// context) would leave earlier lines to glue onto the next message.
|
||||
seedNativeChatLaunchDraftForAgentTab({ tabId, agent, text: content })
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user