merge issue/0109b3-tooltip-claude-fix
Tooltip flash fix + Claude fix button. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,8 @@
|
||||
#include <imgui.h>
|
||||
#ifdef _WIN32
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# include <windows.h>
|
||||
#endif
|
||||
#include "app_base.h"
|
||||
#include "core/panel_menu.h"
|
||||
#include "core/icons_tabler.h"
|
||||
@@ -164,6 +168,56 @@ static double now_seconds() {
|
||||
return duration_cast<duration<double>>(steady_clock::now().time_since_epoch()).count();
|
||||
}
|
||||
|
||||
// Lanza terminal externa con `claude --dangerously-skip-permissions` en el
|
||||
// repo fn_registry. En Windows usa Windows Terminal + WSL; en Linux usa el
|
||||
// primer emulador disponible. Fire-and-forget; no captura output.
|
||||
static bool spawn_claude_terminal(const fs::path& registry_root) {
|
||||
#ifdef _WIN32
|
||||
// wt.exe lanza Windows Terminal. wsl.exe --cd cambia cwd antes del comando.
|
||||
// Bash -ic para que /etc/profile cargue PATH (claude esta en ~/.local/bin
|
||||
// o equivalente). Sin comillas el resto del comando.
|
||||
std::string cmd = "wt.exe new-tab wsl.exe --cd ~/fn_registry -- bash -ic \"claude --dangerously-skip-permissions\"";
|
||||
STARTUPINFOA si{}; si.cb = sizeof(si);
|
||||
PROCESS_INFORMATION pi{};
|
||||
std::string mutable_cmd = cmd; // CreateProcessA needs non-const
|
||||
BOOL ok = CreateProcessA(nullptr, mutable_cmd.data(), nullptr, nullptr, FALSE,
|
||||
CREATE_NEW_CONSOLE, nullptr, nullptr, &si, &pi);
|
||||
if (!ok) {
|
||||
// Fallback: cmd.exe + start wt.exe (less reliable but works without explicit path).
|
||||
std::string fb = "cmd.exe /C start \"\" wt.exe wsl.exe --cd ~/fn_registry -- bash -ic \"claude --dangerously-skip-permissions\"";
|
||||
mutable_cmd = fb;
|
||||
ok = CreateProcessA(nullptr, mutable_cmd.data(), nullptr, nullptr, FALSE,
|
||||
CREATE_NEW_CONSOLE, nullptr, nullptr, &si, &pi);
|
||||
}
|
||||
if (ok) {
|
||||
CloseHandle(pi.hProcess);
|
||||
CloseHandle(pi.hThread);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
#else
|
||||
// Linux: probar varios emuladores comunes.
|
||||
const std::string cd = "cd '" + registry_root.string() + "' && exec claude --dangerously-skip-permissions";
|
||||
const char* candidates[] = {
|
||||
"x-terminal-emulator", "gnome-terminal", "konsole", "xterm", "alacritty", "kitty",
|
||||
};
|
||||
for (const char* term : candidates) {
|
||||
std::string probe = std::string("command -v ") + term + " >/dev/null 2>&1";
|
||||
int probe_rc = std::system(probe.c_str());
|
||||
if (probe_rc != 0) continue;
|
||||
std::string cmd;
|
||||
if (std::string(term) == "gnome-terminal") {
|
||||
cmd = std::string(term) + " -- bash -ic \"" + cd + "\" &";
|
||||
} else {
|
||||
cmd = std::string(term) + " -e bash -ic \"" + cd + "\" &";
|
||||
}
|
||||
(void)!std::system(cmd.c_str());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
// ---- Scanner ------------------------------------------------------------
|
||||
|
||||
static void scan_dir(const fs::path& dir, NodeKind kind, ScanResult& out) {
|
||||
@@ -614,15 +668,20 @@ static void draw_canvas() {
|
||||
dl->AddText(tp, IM_COL32(255, 255, 255, 245), lbl);
|
||||
}
|
||||
|
||||
// Tooltip on hover (title).
|
||||
// Tooltip on hover (title). Fix width up-front so the first frame
|
||||
// doesnt flash a giant window before reflow.
|
||||
if (over) {
|
||||
const float kTipW = 360.0f;
|
||||
ImGui::SetNextWindowSize(ImVec2(kTipW, 0.0f), ImGuiCond_Always);
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::PushTextWrapPos(kTipW - 16.0f);
|
||||
ImGui::Text("%s %s", n.kind == NodeKind::Issue ? "[ISSUE]" : "[FLOW]", n.id.c_str());
|
||||
ImGui::TextWrapped("%s", n.title.c_str());
|
||||
ImGui::TextDisabled("status: %s · ring: %s · domain: %s",
|
||||
n.status_eff.c_str(),
|
||||
ring_label(n.ring),
|
||||
n.domain.empty() ? "?" : n.domain.front().c_str());
|
||||
ImGui::PopTextWrapPos();
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
};
|
||||
@@ -716,6 +775,42 @@ static void draw_inspector() {
|
||||
for (const auto& r : n.related) ImGui::BulletText("%s", r.c_str());
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
// === Claude fix: lanza terminal externa con claude ===
|
||||
static double s_last_launch_t = -1e9;
|
||||
static bool s_last_launch_ok = true;
|
||||
static std::string s_last_launch_id;
|
||||
|
||||
const Bucket b = status_bucket(n.status_eff);
|
||||
const bool fixable = (b != Bucket::Done);
|
||||
if (fixable) {
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, IM_COL32(168, 85, 247, 200));
|
||||
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, IM_COL32(192, 132, 252, 240));
|
||||
ImGui::PushStyleColor(ImGuiCol_ButtonActive, IM_COL32(147, 51, 234, 255));
|
||||
if (ImGui::Button(TI_TERMINAL_2 " Claude fix")) {
|
||||
s_last_launch_ok = spawn_claude_terminal(g_root);
|
||||
s_last_launch_t = now_seconds();
|
||||
s_last_launch_id = n.id;
|
||||
fn_log::log_info("skill_tree: spawn claude terminal for %s -> %s",
|
||||
n.id.c_str(), s_last_launch_ok ? "ok" : "fail");
|
||||
}
|
||||
ImGui::PopStyleColor(3);
|
||||
ImGui::SameLine();
|
||||
ImGui::TextDisabled("abre terminal externa con `claude --dangerously-skip-permissions` en fn_registry");
|
||||
} else {
|
||||
ImGui::TextDisabled("Issue done — no fix necesario.");
|
||||
}
|
||||
if (s_last_launch_id == n.id && (now_seconds() - s_last_launch_t) < 5.0) {
|
||||
if (s_last_launch_ok) {
|
||||
ImGui::TextColored(ImVec4(0.4f, 0.95f, 0.5f, 1.0f),
|
||||
TI_CHECK " terminal lanzada (revisa Windows Terminal / WSL)");
|
||||
} else {
|
||||
ImGui::TextColored(ImVec4(1.0f, 0.5f, 0.5f, 1.0f),
|
||||
TI_ALERT_TRIANGLE " no se pudo lanzar terminal");
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
ImGui::TextDisabled("Botones [Generate ideas] / [Run autonomous-task] llegan en 0109e/f.");
|
||||
ImGui::End();
|
||||
|
||||
Reference in New Issue
Block a user