@@ -6,24 +6,24 @@ import * as os from "os";
66import * as path from "path" ;
77import OpenAI from "openai" ;
88import {
9- SessionManager ,
109 type LlmStreamProgress ,
1110 type MessageMeta ,
1211 type SessionEntry ,
12+ SessionManager ,
1313 type SessionMessage ,
1414 type SessionStatus ,
1515 type SkillInfo ,
1616 type UserPromptContent ,
1717} from "../session" ;
1818import {
1919 applyModelConfigSelection ,
20- resolveSettingsSources ,
2120 type DeepcodingSettings ,
2221 type ModelConfigSelection ,
2322 type ResolvedDeepcodingSettings ,
23+ resolveSettingsSources ,
2424} from "../settings" ;
2525import { PromptInput , type PromptSubmission } from "./PromptInput" ;
26- import { MessageView } from "./MessageView " ;
26+ import { MessageView , RawModeExitPrompt } from "./compoments " ;
2727import { SessionList } from "./SessionList" ;
2828import { buildLoadingText } from "./loadingText" ;
2929import { findExpandedThinkingId } from "./thinkingState" ;
@@ -32,11 +32,13 @@ import { AskUserQuestionPrompt } from "./AskUserQuestionPrompt";
3232import { McpStatusList } from "./McpStatusList" ;
3333import { ProcessStdoutView } from "./ProcessStdoutView" ;
3434import {
35+ type AskUserQuestionAnswers ,
3536 findPendingAskUserQuestion ,
3637 formatAskUserQuestionAnswers ,
37- type AskUserQuestionAnswers ,
3838} from "./askUserQuestion" ;
3939import { buildExitSummaryText } from "./exitSummary" ;
40+ import { RawMode , useRawModeContext } from "./contexts" ;
41+ import { renderMessageToStdout } from "./compoments/MessageView/utils" ;
4042
4143const DEFAULT_MODEL = "deepseek-v4-pro" ;
4244const DEFAULT_BASE_URL = "https://api.deepseek.com" ;
@@ -45,12 +47,11 @@ type View = "chat" | "session-list" | "mcp-status";
4547
4648type AppProps = {
4749 projectRoot : string ;
48- version ?: string ;
4950 initialPrompt ?: string ;
5051 onRestart ?: ( ) => void ;
5152} ;
5253
53- export function App ( { projectRoot, version = "" , initialPrompt, onRestart } : AppProps ) : React . ReactElement {
54+ export function App ( { projectRoot, initialPrompt, onRestart } : AppProps ) : React . ReactElement {
5455 const { exit } = useApp ( ) ;
5556 const { stdout, write } = useStdout ( ) ;
5657 const { columns } = useWindowSize ( ) ;
@@ -75,6 +76,10 @@ export function App({ projectRoot, version = "", initialPrompt, onRestart }: App
7576 const [ showProcessStdout , setShowProcessStdout ] = useState ( false ) ;
7677 const processStdoutRef = useRef < Map < number , string > > ( new Map ( ) ) ;
7778
79+ const { mode, setMode } = useRawModeContext ( ) ;
80+ const rawModeRef = useRef < RawMode > ( mode ) ;
81+ rawModeRef . current = mode ;
82+
7883 const messagesRef = useRef < SessionMessage [ ] > ( [ ] ) ;
7984 messagesRef . current = messages ;
8085
@@ -86,6 +91,10 @@ export function App({ projectRoot, version = "", initialPrompt, onRestart }: App
8691 renderMarkdown : ( text ) => text ,
8792 onAssistantMessage : ( message : SessionMessage ) => {
8893 setMessages ( ( prev ) => [ ...prev , message ] ) ;
94+ if ( rawModeRef . current === RawMode . Raw ) {
95+ process . stdout . write ( "\n" ) ;
96+ process . stdout . write ( renderMessageToStdout ( message , rawModeRef . current ) + "\n\n" ) ;
97+ }
8998 } ,
9099 onSessionEntryUpdated : ( entry ) => {
91100 setStatusLine ( buildStatusLine ( entry ) ) ;
@@ -362,6 +371,39 @@ export function App({ projectRoot, version = "", initialPrompt, onRestart }: App
362371 [ sessionManager , refreshSkills ]
363372 ) ;
364373
374+ const handleRawModeChange = useCallback (
375+ ( nextMode : string ) => {
376+ const activeSessionId = sessionManager . getActiveSessionId ( ) ;
377+ if ( ! activeSessionId ) {
378+ return ;
379+ }
380+
381+ setMode ( nextMode as RawMode ) ;
382+
383+ // Clear screen to remove stale formatted text.
384+ process . stdout . write ( "\u001B[2J\u001B[3J\u001B[H" ) ;
385+
386+ setTimeout ( ( ) => {
387+ if ( nextMode === RawMode . Raw ) {
388+ // Write all messages directly to stdout for raw scrollback mode.
389+ const allMessages = loadVisibleMessages ( sessionManager , activeSessionId ) ;
390+ for ( const msg of allMessages ) {
391+ process . stdout . write ( "\n" ) ;
392+ process . stdout . write ( renderMessageToStdout ( msg , nextMode ) + "\n\n" ) ;
393+ }
394+ if ( allMessages . length > 0 ) {
395+ process . stdout . write ( "\n\n" ) ;
396+ process . stdout . write ( chalk . dim ( "Press ESC to exit raw mode" ) ) ;
397+ }
398+ } else {
399+ // Switch to chat view to render messages.
400+ handleSelectSession ( activeSessionId ) ;
401+ }
402+ } , 200 ) ;
403+ } ,
404+ [ handleSelectSession , sessionManager , setMode ]
405+ ) ;
406+
365407 const [ stableColumns , setStableColumns ] = useState ( columns ) ;
366408 useEffect ( ( ) => {
367409 const timer = setTimeout ( ( ) => setStableColumns ( columns ) , 100 ) ;
@@ -413,7 +455,7 @@ export function App({ projectRoot, version = "", initialPrompt, onRestart }: App
413455 // eslint-disable-next-line react-hooks/exhaustive-deps -- nowTick forces periodic recalculation for spinner animation
414456 [ busy , streamProgress , runningProcesses , nowTick ]
415457 ) ;
416- const welcomeSettings = resolvedSettings ;
458+
417459 const welcomeItem : SessionMessage = useMemo (
418460 ( ) => ( {
419461 id : `__welcome__${ welcomeNonce } ` ,
@@ -430,11 +472,14 @@ export function App({ projectRoot, version = "", initialPrompt, onRestart }: App
430472 [ welcomeNonce ]
431473 ) ;
432474 const staticItems = useMemo ( ( ) => {
475+ if ( mode === RawMode . Raw ) {
476+ return [ ] ;
477+ }
433478 if ( showWelcome && view === "chat" ) {
434479 return [ welcomeItem , ...messages ] ;
435480 }
436481 return messages ;
437- } , [ showWelcome , view , messages , welcomeItem ] ) ;
482+ } , [ mode , showWelcome , view , messages , welcomeItem ] ) ;
438483
439484 const handleQuestionAnswers = useCallback (
440485 ( answers : AskUserQuestionAnswers ) => {
@@ -453,6 +498,10 @@ export function App({ projectRoot, version = "", initialPrompt, onRestart }: App
453498 setDismissedQuestionIds ( ( prev ) => new Set ( prev ) . add ( pendingQuestion . messageId ) ) ;
454499 } , [ pendingQuestion ] ) ;
455500
501+ if ( mode === RawMode . Raw ) {
502+ return < RawModeExitPrompt onExit = { ( ) => handleRawModeChange ( RawMode . None ) } /> ;
503+ }
504+
456505 return (
457506 < Box flexDirection = "column" width = { screenWidth } minWidth = { 80 } overflowX = { "visible" } >
458507 < Static items = { staticItems } >
@@ -462,9 +511,8 @@ export function App({ projectRoot, version = "", initialPrompt, onRestart }: App
462511 < WelcomeScreen
463512 key = { item . id }
464513 projectRoot = { projectRoot }
465- settings = { welcomeSettings }
514+ settings = { resolvedSettings }
466515 skills = { skills }
467- version = { version }
468516 width = { screenWidth }
469517 />
470518 ) ;
@@ -521,6 +569,7 @@ export function App({ projectRoot, version = "", initialPrompt, onRestart }: App
521569 runningProcesses = { runningProcesses }
522570 onSubmit = { handleSubmit }
523571 onModelConfigChange = { handleModelConfigChange }
572+ onRawModeChange = { handleRawModeChange }
524573 onInterrupt = { handleInterrupt }
525574 onToggleProcessStdout = { handleToggleProcessStdout }
526575 placeholder = "Type your message..."
0 commit comments