Live mode: an AI assistant acts on the open project while the user watches

A new setting, Configurer QElectroTech > Général > "Autoriser un assistant
IA à agir sur le projet ouvert", off by default. Off, nothing changes:
no channel is opened. On, every start shows a warning first -- Continuer,
Pas pour cette session, or Désactiver -- and nothing can connect until
the user answers Continuer. It waits for any other start-up question to
be answered, so the two never stack.

Accepted, LiveServer opens a local socket only the user's account can
use, with a random name and token written to live-session.json in the
data folder for the qet MCP server, and removed when the channel closes.
One JSON request per line: status (project, folio on screen, selection,
last undo step, stored scripts), run_script and run_stored. Requests are
queued out of the socket handler before they run (the lesson of PR #861).

Each run is one undo step named "Assistant : <name>". The status bar
shows the mode and the assistant's last action with a ✓ or ✗ and the
time, and an Arrêter button that closes the channel for the session.
Unticking the setting closes it at once.

QetScripting::runSource() runs script text and, for a live run, returns
what qet.log() wrote, the error with its line and the undo step instead
of showing boxes; qet.showMessage() is logged rather than opening a box
nobody asked for.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ispyisail
2026-10-02 10:31:08 +13:00
parent 4f47093cb2
commit 2fb14c5bd0
13 changed files with 619 additions and 15 deletions
+16
View File
@@ -393,6 +393,18 @@ bool QetScriptApi::save(const QString &output)
void QetScriptApi::log(const QString &message)
{
QTextStream(stderr) << message << "\n";
if (m_live_log) m_live_log->append(message);
}
/**
@brief QetScriptApi::setLive
A run asked for by an assistant (LiveServer): what the script logs is
collected in @p log for the answer, and a message box -- which would
wait for someone who did not ask for it -- is logged instead.
*/
void QetScriptApi::setLive(QStringList *log)
{
m_live_log = log;
}
/**
@@ -4386,5 +4398,9 @@ bool QetScriptApi::zoomReset()
*/
void QetScriptApi::showMessage(const QString &text)
{
if (m_live_log) {
log(QStringLiteral("qet.showMessage: ") + text);
return;
}
QET::QetMessageBox::information(nullptr, QObject::tr("Script"), text);
}