mirror of
https://github.com/stablyai/orca.git
synced 2026-09-28 08:02:43 +00:00
codex: mark streamed reasoning as reasoning too, and pin the provider markers
The settled reasoning item carried the marker but the streaming one did not, so a live Codex turn - the only time the indicator is on screen - never read as reasoning. Both paths now stamp it; a plan document keeps its own presentation and must never read as reasoning.
This commit is contained in:
@@ -2,11 +2,12 @@ import { mkdtemp, rm } from 'node:fs/promises'
|
||||
import { tmpdir } from 'node:os'
|
||||
import { join } from 'node:path'
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import type {
|
||||
AgentJournalItemBody,
|
||||
AgentJournalItemIdentity,
|
||||
AgentJournalRenderItem,
|
||||
AgentSessionJournalIdentity
|
||||
import {
|
||||
AGENT_JOURNAL_THINKING_PRESENTATION,
|
||||
type AgentJournalItemBody,
|
||||
type AgentJournalItemIdentity,
|
||||
type AgentJournalRenderItem,
|
||||
type AgentSessionJournalIdentity
|
||||
} from '../../shared/agent-session-journal-types'
|
||||
import { agentJournalItemKey } from '../../shared/agent-session-journal-item-key'
|
||||
import { activeStructuredAgentSessionTurnId } from '../../shared/structured-agent-session-projection'
|
||||
@@ -568,7 +569,9 @@ describe('Claude structured journal translation', () => {
|
||||
|
||||
expect(state.items.at(-1)?.body).toEqual({
|
||||
kind: 'status',
|
||||
text: boundInlineText(thinking, DEFAULT_JOURNAL_PAYLOAD_LIMITS).text
|
||||
text: boundInlineText(thinking, DEFAULT_JOURNAL_PAYLOAD_LIMITS).text,
|
||||
// Marks the row as the model reasoning, so a client can label the live turn.
|
||||
presentation: AGENT_JOURNAL_THINKING_PRESENTATION
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { codexItemBody, codexStreamingJournalItem } from './codex-structured-item-translation'
|
||||
import { AgentJournalItemBodySchema } from '../../shared/agent-session-journal-schemas'
|
||||
import { AGENT_JOURNAL_THINKING_PRESENTATION } from '../../shared/agent-session-journal-types'
|
||||
import { projectStructuredItemsToNativeChat } from '../../shared/structured-agent-session-projection'
|
||||
|
||||
describe('plan document translation', () => {
|
||||
@@ -23,10 +24,15 @@ describe('plan document translation', () => {
|
||||
codexItemBody({ id: 'r', type: 'reasoning', summary: ['Thinking through the problem.'] })
|
||||
).toEqual({
|
||||
kind: 'status',
|
||||
text: 'Thinking through the problem.'
|
||||
text: 'Thinking through the problem.',
|
||||
presentation: AGENT_JOURNAL_THINKING_PRESENTATION
|
||||
})
|
||||
expect(codexStreamingJournalItem({ id: 'r', type: 'reasoning' }, 'Thinking…')).toEqual({
|
||||
body: { kind: 'status', text: 'Thinking…' },
|
||||
body: {
|
||||
kind: 'status',
|
||||
text: 'Thinking…',
|
||||
presentation: AGENT_JOURNAL_THINKING_PRESENTATION
|
||||
},
|
||||
handled: true
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { agentJournalItemKey } from '../../shared/agent-session-journal-item-key'
|
||||
import { AGENT_JOURNAL_THINKING_PRESENTATION } from '../../shared/agent-session-journal-types'
|
||||
import {
|
||||
briefToolArg,
|
||||
createToolInputDisplay,
|
||||
@@ -592,12 +593,17 @@ describe('codex item bodies', () => {
|
||||
body: { kind: 'status', text, presentation: 'plan-document' },
|
||||
handled: true
|
||||
})
|
||||
// A plan is a durable artifact, so it must never read as the model reasoning now.
|
||||
expect(codexItemBody({ type: 'plan', id: 'plan-document', text })).not.toMatchObject({
|
||||
presentation: AGENT_JOURNAL_THINKING_PRESENTATION
|
||||
})
|
||||
})
|
||||
|
||||
it('renders reasoning as status and exposes an unknown item as a provider frame', () => {
|
||||
expect(codexItemBody({ type: 'reasoning', id: 'r', text: 'thinking' })).toEqual({
|
||||
kind: 'status',
|
||||
text: 'thinking'
|
||||
text: 'thinking',
|
||||
presentation: AGENT_JOURNAL_THINKING_PRESENTATION
|
||||
})
|
||||
expect(codexItemBody({ type: 'reasoning', id: 'r' })).toBeNull()
|
||||
expect(codexItemBody({ type: 'agentMessage', id: 'm', text: '' })).toBeNull()
|
||||
@@ -830,7 +836,11 @@ describe('codex item bodies', () => {
|
||||
summary: ['first', 'second'],
|
||||
content: [{ text: 'fallback' }]
|
||||
})
|
||||
).toEqual({ kind: 'status', text: 'first\nsecond' })
|
||||
).toEqual({
|
||||
kind: 'status',
|
||||
text: 'first\nsecond',
|
||||
presentation: AGENT_JOURNAL_THINKING_PRESENTATION
|
||||
})
|
||||
})
|
||||
|
||||
it('refuses a value that is not a thread item at all', () => {
|
||||
|
||||
@@ -337,5 +337,14 @@ export function codexStreamingJournalItem(item: CodexThreadItem, text: string):
|
||||
}
|
||||
}
|
||||
const bounded = boundInlineText(text, DEFAULT_JOURNAL_PAYLOAD_LIMITS)
|
||||
return { body: { kind: 'status', text: bounded.text }, handled: true }
|
||||
return {
|
||||
body: {
|
||||
kind: 'status',
|
||||
text: bounded.text,
|
||||
// Streaming reasoning is the live turn's reasoning; the settled item says so
|
||||
// too, and the indicator reads the tail of the journal while it is still open.
|
||||
...(item.type === 'reasoning' ? { presentation: AGENT_JOURNAL_THINKING_PRESENTATION } : {})
|
||||
},
|
||||
handled: true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import {
|
||||
CODEX_USER_INPUT_METHOD
|
||||
} from './codex-structured-prompt-replies'
|
||||
import type { CodexStructuredSessionEvent } from './codex-structured-session-adapter'
|
||||
import { AGENT_JOURNAL_THINKING_PRESENTATION } from '../../shared/agent-session-journal-types'
|
||||
|
||||
const SESSION_ID = 'session-1'
|
||||
const THREAD_ID = 'thread-abc'
|
||||
@@ -800,7 +801,9 @@ describe('codex journal translation', () => {
|
||||
const reduced = new Map(tap.rows.map((row) => [row.key, row.body]))
|
||||
expect(reduced.get('orca:codex-item%3Athread-abc%3Ar-1')).toEqual({
|
||||
kind: 'status',
|
||||
text: 'thinking'
|
||||
text: 'thinking',
|
||||
// A streamed reasoning row is still reasoning, so the live indicator can read it.
|
||||
presentation: AGENT_JOURNAL_THINKING_PRESENTATION
|
||||
})
|
||||
expect(reduced.get('orca:codex-item%3Athread-abc%3Apatch-1')).toMatchObject({
|
||||
kind: 'diff',
|
||||
|
||||
Reference in New Issue
Block a user