fix: the window's approval switch never reached the engine
needs_confirm() (src/agent_loop.c) decides whether a tool asks by reading cfg->confirm_shell / confirm_write / confirm_net; the approval mode only relaxes those. The CLI fills them in (main.c: parse_confirm), the TUI and the WebUI do too -- the Qt window never did: AgentCore::open() memset the whole config and cst_agent_create() keeps what it is given, so every tool ran without asking while the sidebar said "ask". That is why nothing was ever asked on the phone (or on a desktop). - AgentCore: one mapping, applyApproval(), used by open() and setApproval(); the mode is remembered like the TUI's /approval and read back on start (else "ask", the only mode where the window's consent dialog is reached). - --uitest: two checks that the mode reaches the engine as those flags. Version 0.9.7 (local).
This commit is contained in:
@@ -45,6 +45,24 @@ class Turn : public QThread {
|
|||||||
QByteArray m_prompt;
|
QByteArray m_prompt;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* The engine asks for a tool only when its own confirm_shell / confirm_write /
|
||||||
|
* confirm_net flag says so (`needs_confirm()`, src/agent_loop.c) -- the
|
||||||
|
* approval mode on top of that only *relaxes* them (AUTO writes a file
|
||||||
|
* without asking, YOLO everything). The CLI fills those three in
|
||||||
|
* (src/main.c: parse_confirm), the TUI and the WebUI do too; the window never
|
||||||
|
* did: AgentCore::open() zeroed the whole config and cst_agent_create() keeps
|
||||||
|
* what it is given, so every tool ran without asking while the sidebar said
|
||||||
|
* "ask". One mapping, used by both open() and setApproval(). */
|
||||||
|
namespace {
|
||||||
|
void applyApproval(cst_agent_config_t *cfg, int approval) {
|
||||||
|
const int ask = (approval == CST_APPROVAL_ASK);
|
||||||
|
cfg->approval = approval;
|
||||||
|
cfg->confirm_shell = ask;
|
||||||
|
cfg->confirm_write = ask;
|
||||||
|
cfg->confirm_net = ask;
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
/* --- lifetime ------------------------------------------------------------ */
|
/* --- lifetime ------------------------------------------------------------ */
|
||||||
|
|
||||||
AgentCore::AgentCore(QObject *parent) : QObject(parent) {
|
AgentCore::AgentCore(QObject *parent) : QObject(parent) {
|
||||||
@@ -141,6 +159,14 @@ bool AgentCore::open(const QString &workspace, const QString &provider,
|
|||||||
/* The GUI answers itself: never let the engine decide behind its back. */
|
/* The GUI answers itself: never let the engine decide behind its back. */
|
||||||
m_cfg.auto_approve = 0;
|
m_cfg.auto_approve = 0;
|
||||||
m_cfg.headless = 0;
|
m_cfg.headless = 0;
|
||||||
|
/* What the person chose last -- the CLI and the TUI remember it the same
|
||||||
|
* way and the TUI writes the same file -- else "ask", which is what the
|
||||||
|
* window's default label promises and the only mode where its consent
|
||||||
|
* dialog is ever reached. */
|
||||||
|
int approval = CST_APPROVAL_ASK;
|
||||||
|
if (have_settings && st.approval[0])
|
||||||
|
cst_approval_parse(st.approval, &approval);
|
||||||
|
applyApproval(&m_cfg, approval);
|
||||||
if (!m_cfg.mode[0])
|
if (!m_cfg.mode[0])
|
||||||
snprintf(m_cfg.mode, sizeof(m_cfg.mode), "%s", CST_DEFAULT_MODE);
|
snprintf(m_cfg.mode, sizeof(m_cfg.mode), "%s", CST_DEFAULT_MODE);
|
||||||
m_agent = cst_agent_create(&m_cfg);
|
m_agent = cst_agent_create(&m_cfg);
|
||||||
@@ -395,9 +421,12 @@ void AgentCore::setMode(const QString &mode) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void AgentCore::setApproval(int approval) {
|
void AgentCore::setApproval(int approval) {
|
||||||
m_cfg.approval = approval;
|
applyApproval(&m_cfg, approval);
|
||||||
if (m_agent)
|
if (m_agent)
|
||||||
cst_agent_config_mut(m_agent)->approval = approval;
|
applyApproval(cst_agent_config_mut(m_agent), approval);
|
||||||
|
/* Remembered like the TUI's /approval: the next start of the window (or of
|
||||||
|
* the CLI) comes up the way it was left. */
|
||||||
|
cst_settings_remember_approval(approval);
|
||||||
emit approvalChanged();
|
emit approvalChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -416,6 +416,25 @@ int runUiTest(AgentCore &core, const QString &size) {
|
|||||||
QStringLiteral("and the line is where the card is"));
|
QStringLiteral("and the line is where the card is"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The approval switch is not decoration: the engine asks for a tool only
|
||||||
|
* when its own confirm_* flags say so (needs_confirm() in agent_loop.c),
|
||||||
|
* and every front end that has a consent dialog has to set them -- the
|
||||||
|
* window used to leave all three at zero, which is why "ask" never asked. */
|
||||||
|
{
|
||||||
|
const int was = core.approval();
|
||||||
|
core.setApproval(CST_APPROVAL_ASK);
|
||||||
|
const cst_agent_config_t *live = cst_agent_config(core.agent());
|
||||||
|
check(live && live->approval == CST_APPROVAL_ASK && live->confirm_shell &&
|
||||||
|
live->confirm_write && live->confirm_net,
|
||||||
|
QStringLiteral("'ask' reaches the engine as the three confirm flags"));
|
||||||
|
core.setApproval(CST_APPROVAL_YOLO);
|
||||||
|
live = cst_agent_config(core.agent());
|
||||||
|
check(live && live->approval == CST_APPROVAL_YOLO && !live->confirm_shell &&
|
||||||
|
!live->confirm_write && !live->confirm_net,
|
||||||
|
QStringLiteral("and 'yolo' takes them all away"));
|
||||||
|
core.setApproval(was); /* leave the machine as it was found */
|
||||||
|
}
|
||||||
|
|
||||||
/* --- md_to_pdf: the front end's own document writer ------------------- */
|
/* --- md_to_pdf: the front end's own document writer ------------------- */
|
||||||
{
|
{
|
||||||
const cst_tool_def_t *def = cst_tool_find("md_to_pdf");
|
const cst_tool_def_t *def = cst_tool_find("md_to_pdf");
|
||||||
|
|||||||
Reference in New Issue
Block a user