({ item }: { item: HistoryItem })
| 831 | if (busy || pendingPrompt) { |
| 832 | setQueued(q => [...q, v]); |
| 833 | const preview = v.length > 56 ? v.slice(0, 56) + '…' : v; |
| 834 | setHistory(h => [...h, { type: 'system', text: `Queued — runs when the current task finishes: ${preview}`, id: nextId() }]); |
| 835 | return; |
| 836 | } |
| 837 | void submitPrompt(v); |
| 838 | }, [busy, pendingPrompt, submitPrompt, nextId]); |
| 839 | |
| 840 | // Drain the type-ahead queue: when the agent is idle and no permission prompt is |
| 841 | // open, submit the next queued prompt. One at a time — a real turn flips `busy`, |
| 842 | // which parks this effect until it finishes; instant prompts (e.g. slash commands) |
| 843 | // re-trigger via drainTick. dispatchingRef guards against double-dispatch while a |
| 844 | // queued submit is still settling. |
| 845 | useEffect(() => { |
| 846 | if (busy || pendingPrompt || dispatchingRef.current || queued.length === 0) return; |
| 847 | dispatchingRef.current = true; |
| 848 | const [next, ...rest] = queued; |
| 849 | setQueued(rest); |
| 850 | void submitPrompt(next).finally(() => { |
| 851 | dispatchingRef.current = false; |
| 852 | setDrainTick(t => t + 1); |
| 853 | }); |
| 854 | }, [busy, pendingPrompt, queued, drainTick, submitPrompt]); |
| 855 | |
| 856 | // Welcome as a Static "sentinel" item. By living INSIDE <Static>, it gets painted |
| 857 | // once and never repainted on subsequent re-renders — fixing the re-flash we'd see |
| 858 | // on every state change. The renderer closure has access to props directly. |
| 859 | type StaticItem = { kind: 'welcome' } | { kind: 'history'; item: HistoryItem }; |
| 860 | const staticItems: StaticItem[] = React.useMemo( |
| 861 | () => [{ kind: 'welcome' as const }, ...history.map(item => ({ kind: 'history' as const, item }))], |
| 862 | [history], |
| 863 | ); |
| 864 | |
| 865 | // Animated launch experience. Plays once, then collapses into the Welcome header. |
| 866 | if (!booted) { |
| 867 | return ( |
| 868 | <BootSplash |
| 869 | cwd={props.cwd} |
| 870 | config={props.config} |
| 871 | registry={props.registry} |
| 872 | router={props.router} |
| 873 | onDone={() => setBooted(true)} |
nothing calls this directly
no test coverage detected