@@ -205,6 +205,11 @@ AcpSessionView::AcpSessionView(AcpSessionModel *model,
205205
206206AcpSessionView::~AcpSessionView () = default ;
207207
208+ QSize AcpSessionView::sizeHint () const
209+ {
210+ return QSize (420 , 300 );
211+ }
212+
208213QSize AcpSessionView::minimumSizeHint () const
209214{
210215 return QSize (200 , 100 );
@@ -434,6 +439,13 @@ void AcpSessionView::buildUi()
434439 cb->onSubmit = [this ]() { onSendClicked (); };
435440 cb->onRestart = [this ]() { emit restartSessionRequested (); };
436441 cb->onKeyFilter = [this ](QKeyEvent *ke) -> bool {
442+ // Esc cancels prompt improvement if streaming.
443+ if (ke->key () == Qt::Key_Escape
444+ && m_promptImprover
445+ && m_promptImprover->state () == ai::PromptImprover::State::Streaming) {
446+ onImproveClicked (); // toggles to cancel
447+ return true ;
448+ }
437449 if (!m_commandPopup || !m_commandPopup->isVisible ())
438450 return false ;
439451 switch (ke->key ()) {
@@ -496,16 +508,16 @@ void AcpSessionView::buildUi()
496508 // 6b. Floating improve-prompt button (child of m_input, bottom-right).
497509 m_improveBtn = new QToolButton (m_input->viewport ());
498510 m_improveBtn->setAutoRaise (true );
499- m_improveBtn->setToolButtonStyle (Qt::ToolButtonIconOnly);
511+ m_improveBtn->setToolButtonStyle (Qt::ToolButtonTextOnly);
512+ m_improveBtn->setText (QStringLiteral (" ✨" ));
500513 m_improveBtn->setToolTip (tr (" Improve prompt with AI (Ctrl+I)" ));
501514 m_improveBtn->setAccessibleName (tr (" Improve prompt with AI" ));
502515 m_improveBtn->setAccessibleDescription (tr (" Rewrite the current prompt to be clearer (Ctrl+I)" ));
503516 m_improveBtn->setCursor (Qt::PointingHandCursor);
504517 m_improveBtn->setStyleSheet (QStringLiteral (
505- " QToolButton { background: transparent; border: none; padding: 2px; border-radius: 3px; }"
518+ " QToolButton { background: transparent; border: none; padding: 2px; border-radius: 3px; font-size: 14px; }"
506519 " QToolButton:hover { background: palette(midlight); }"
507520 " QToolButton:disabled { opacity: 0.3; }" ));
508- rebuildImproveIcon ();
509521 m_improveBtn->hide ();
510522 connect (m_improveBtn, &QToolButton::clicked, this , &AcpSessionView::onImproveClicked);
511523
@@ -1751,7 +1763,6 @@ void AcpSessionView::changeEvent(QEvent *event)
17511763 case QEvent::StyleChange:
17521764 case QEvent::ApplicationPaletteChange:
17531765 rebuildAttachIcon ();
1754- rebuildImproveIcon ();
17551766 break ;
17561767 default :
17571768 break ;
@@ -1765,13 +1776,6 @@ void AcpSessionView::rebuildAttachIcon()
17651776 palette ().color (QPalette::WindowText)));
17661777}
17671778
1768- void AcpSessionView::rebuildImproveIcon ()
1769- {
1770- if (!m_improveBtn) return ;
1771- m_improveBtn->setIcon (tintedIcon (QStringLiteral (" :/icons/sparkle.svg" ),
1772- palette ().color (QPalette::WindowText)));
1773- }
1774-
17751779void AcpSessionView::applyChatFont ()
17761780{
17771781 auto *settings = appSettings ();
@@ -1914,16 +1918,29 @@ void AcpSessionView::updateImproveButtonState()
19141918
19151919 m_improveBtn->show ();
19161920 positionImproveButton ();
1917-
1918- // Disable when streaming or LLM not configured.
1919- const bool canFire = m_promptImprover && m_promptImprover->canImprove ();
1920- m_improveBtn->setEnabled (canFire);
1921+ m_improveBtn->setEnabled (true );
19211922}
19221923
19231924void AcpSessionView::onImproveClicked ()
19241925{
19251926 if (!m_promptImprover || !m_input) return ;
1926- if (!m_promptImprover->canImprove ()) return ;
1927+
1928+ // If already streaming, cancel.
1929+ if (m_promptImprover->state () == ai::PromptImprover::State::Streaming) {
1930+ m_promptImprover->cancel ();
1931+ m_input->setReadOnly (false );
1932+ m_improveBtn->setText (QStringLiteral (" ✨" ));
1933+ m_improveBtn->setToolTip (tr (" Improve prompt with AI (Ctrl+I)" ));
1934+ updateImproveButtonState ();
1935+ return ;
1936+ }
1937+
1938+ QString whyNot;
1939+ if (!m_promptImprover->canImprove (&whyNot)) {
1940+ setBanner (whyNot, BannerKind::Warning);
1941+ QTimer::singleShot (5000 , this , &AcpSessionView::clearBanner);
1942+ return ;
1943+ }
19271944
19281945 const QString draft = m_input->toPlainText ().trimmed ();
19291946 if (draft.isEmpty ()) return ;
@@ -1940,12 +1957,43 @@ void AcpSessionView::onImproveClicked()
19401957 const QList<AcpProtocol::AcpCommandInfo> commands =
19411958 m_model ? m_model->availableCommands () : QList<AcpProtocol::AcpCommandInfo>{};
19421959
1960+ // Build a condensed chat history from recent messages (budget: ~4000 chars).
1961+ QString chatHistory;
1962+ if (m_model) {
1963+ constexpr int kHistoryBudget = 4000 ;
1964+ const auto &msgs = m_model->messages ();
1965+ int totalChars = 0 ;
1966+ // Walk backwards to get the most recent messages first.
1967+ for (int i = msgs.size () - 1 ; i >= 0 ; --i) {
1968+ const auto &msg = msgs[i];
1969+ if (msg.role != QLatin1String (" user" ) && msg.role != QLatin1String (" assistant" ))
1970+ continue ;
1971+ QString text;
1972+ for (const auto &block : msg.content ) {
1973+ if (block.kind == AcpProtocol::AcpContentBlock::Kind::Text)
1974+ text += block.text ;
1975+ }
1976+ text = text.trimmed ();
1977+ if (text.isEmpty ()) continue ;
1978+ // Truncate individual messages that are too long.
1979+ if (text.size () > 800 )
1980+ text = text.left (800 ) + QStringLiteral (" ..." );
1981+ const QString entry = QStringLiteral (" [%1]: %2\n " ).arg (msg.role , text);
1982+ if (totalChars + entry.size () > kHistoryBudget )
1983+ break ;
1984+ chatHistory.prepend (entry);
1985+ totalChars += entry.size ();
1986+ }
1987+ chatHistory = chatHistory.trimmed ();
1988+ }
1989+
19431990 m_originalDraftBeforeImprove = m_input->toPlainText ();
19441991 m_input->setReadOnly (true );
1945- m_improveBtn->setEnabled (false );
1946- m_improveBtn->setToolTip (tr (" Improving prompt..." ));
1992+ m_improveBtn->setText (QStringLiteral (" ■" ));
1993+ m_improveBtn->setToolTip (tr (" Stop improving (Esc)" ));
1994+ m_improveBtn->setEnabled (true );
19471995
1948- m_promptImprover->trigger (draft, workingDir, commands);
1996+ m_promptImprover->trigger (draft, workingDir, commands, chatHistory );
19491997}
19501998
19511999void AcpSessionView::onImproveFinished (const QString &improvedText)
@@ -1961,6 +2009,7 @@ void AcpSessionView::onImproveFinished(const QString &improvedText)
19612009 cursor.endEditBlock ();
19622010
19632011 m_input->setReadOnly (false );
2012+ m_improveBtn->setText (QStringLiteral (" ✨" ));
19642013 m_improveBtn->setToolTip (tr (" Improve prompt with AI (Ctrl+I)" ));
19652014 m_input->setFocus ();
19662015 updateImproveButtonState ();
@@ -1971,6 +2020,7 @@ void AcpSessionView::onImproveError(const QString &message)
19712020 if (!m_input) return ;
19722021
19732022 m_input->setReadOnly (false );
2023+ m_improveBtn->setText (QStringLiteral (" ✨" ));
19742024 m_improveBtn->setToolTip (tr (" Improve prompt with AI (Ctrl+I)" ));
19752025 updateImproveButtonState ();
19762026
0 commit comments