MCPcopy Create free account
hub / github.com/QodeXcli/QodeX / App

Function App

src/cli/ui.tsx:74–734  ·  view source on GitHub ↗
(props: AppProps)

Source from the content-addressed store, hash-verified

72}
73
74export function App(props: AppProps): React.ReactElement {
75 const { exit } = useApp();
76 // Pre-compute resumed-session metadata for the welcome banner
77 const resumedMeta = (() => {
78 if (!props.resumeSessionId) return undefined;
79 try {
80 const loaded = getSessionStore().loadSession(props.resumeSessionId);
81 if (loaded) return { id: props.resumeSessionId, turnCount: loaded.meta.turn_count };
82 } catch { /* ignore */ }
83 return undefined;
84 })();
85 const [history, setHistory] = useState<HistoryItem[]>(() => {
86 // On resume, repaint the prior Q&A so the user sees the conversation they're
87 // continuing — not a blank screen. (The model's context is rehydrated separately
88 // via `messages` below; this is purely the on-screen transcript.)
89 if (props.resumeSessionId) {
90 try {
91 const loaded = getSessionStore().loadSession(props.resumeSessionId);
92 if (loaded) return messagesToHistory(loaded.messages);
93 } catch { /* ignore — fall back to empty */ }
94 }
95 return [];
96 });
97 const [input, setInput] = useState('');
98 // Type-ahead queue: prompts the user submits while a turn is running. They run
99 // one at a time as soon as the agent goes idle (drained by an effect below), so
100 // the input box stays usable mid-task — like Claude Code's queued input.
101 const [queued, setQueued] = useState<string[]>([]);
102 // Bumped after each queued prompt finishes to re-trigger the drain effect even
103 // when the prompt didn't flip `busy` (e.g. an instant slash command).
104 const [drainTick, setDrainTick] = useState(0);
105 const dispatchingRef = useRef(false);
106 // Up/Down-arrow recall of previously submitted prompts (shell-style history),
107 // consumed by ChatInput.
108 const promptHistoryRef = useRef<string[]>([]);
109 const [busy, setBusy] = useState(false);
110 const [streamingText, setStreamingText] = useState('');
111 const [activeTools, setActiveTools] = useState<Array<{ id: string; name: string; partialArgs: string }>>([]);
112 const [pendingPrompt, setPendingPrompt] = useState<PendingPrompt | null>(null);
113 const [sessionId, setSessionId] = useState<string>(() => {
114 const store = getSessionStore();
115 if (props.resumeSessionId) {
116 const loaded = store.loadSession(props.resumeSessionId);
117 if (loaded) return props.resumeSessionId;
118 }
119 return store.createSession(props.cwd, props.config.defaults.model);
120 });
121 const [messages, setMessages] = useState<Message[]>(() => {
122 if (props.resumeSessionId) {
123 const loaded = getSessionStore().loadSession(props.resumeSessionId);
124 if (loaded) return loaded.messages;
125 }
126 return [];
127 });
128 const [mode, setMode] = useState<'normal' | 'plan'>('normal');
129 // Gates the main UI behind the animated boot splash. Flips to true when the splash
130 // finishes (or immediately when motion is disabled / not a TTY).
131 const [booted, setBooted] = useState(false);

Callers

nothing calls this directly

Calls 15

runSubagentMethod · 0.95
getSessionStoreFunction · 0.85
messagesToHistoryFunction · 0.85
handleSlashCommandFunction · 0.85
annotateImagePromptFunction · 0.85
stripLeakedToolTagsFunction · 0.85
stripThinkingForDisplayFunction · 0.85
stripLeakedToolJsonFunction · 0.85
dedupeSelfRepeatedTextFunction · 0.85
isRedundantAssistantTextFunction · 0.85
parseSteerInputFunction · 0.85
tailForViewportFunction · 0.85

Tested by

no test coverage detected