Add step 625 tool call visualization model

This commit is contained in:
Bill
2026-02-17 21:10:53 -07:00
parent 49b80096f1
commit f770f173a0
6 changed files with 301 additions and 0 deletions

View File

@@ -1,6 +1,8 @@
#pragma once
// Step 624: Agent Chat Panel model
#include "AgentToolCallVisualization.h"
#include <cctype>
#include <string>
#include <vector>
@@ -19,6 +21,7 @@ struct AgentChatMessage {
struct AgentChatState {
std::vector<AgentChatMessage> messages;
std::vector<AgentToolCallView> toolCalls;
std::string draftInput;
bool autoScroll = true;
bool open = false;
@@ -52,6 +55,20 @@ public:
state->autoScroll = true;
}
static void addToolCall(AgentChatState* state,
const std::string& toolName,
const json& input,
const json& output,
const std::string& timestamp) {
if (!state) return;
AgentToolCallView view = AgentToolCallVisualization::build(toolName, input, output);
state->toolCalls.push_back(view);
state->messages.push_back({AgentChatRole::Tool,
AgentToolCallVisualization::inlineLabel(view),
timestamp});
state->autoScroll = true;
}
static const char* roleLabel(AgentChatRole role) {
if (role == AgentChatRole::User) return "user";
if (role == AgentChatRole::Assistant) return "assistant";

View File

@@ -0,0 +1,63 @@
#pragma once
// Step 625: Tool call visualization model
#include <nlohmann/json.hpp>
#include <string>
using json = nlohmann::json;
struct AgentToolCallView {
std::string toolName;
std::string summary;
std::string inputJson;
std::string outputJson;
bool expanded = false;
};
class AgentToolCallVisualization {
public:
static AgentToolCallView build(const std::string& toolName,
const json& input,
const json& output) {
AgentToolCallView view;
view.toolName = toolName;
view.summary = summarize(toolName, input);
view.inputJson = input.dump(2);
view.outputJson = output.dump(2);
return view;
}
static std::string inlineLabel(const AgentToolCallView& view) {
const std::string chevron = view.expanded ? "v" : ">";
return "[TOOL: " + view.toolName + "] " + chevron + " " + view.summary;
}
static void toggleExpanded(AgentToolCallView* view) {
if (!view) return;
view->expanded = !view->expanded;
}
private:
static std::string summarize(const std::string& toolName, const json& input) {
if (toolName == "whetstone_mutate") {
std::string type = input.value("type", "mutation");
std::string nodeId = input.value("nodeId", "?");
std::string property = input.value("property", "");
std::string value = input.contains("value") ? input["value"].dump() : "null";
if (!property.empty()) return type + " " + nodeId + "." + property + " -> " + value;
return type + " " + nodeId + " -> " + value;
}
if (toolName == "whetstone_generate_code") {
std::string spec = input.value("spec", "");
if (spec.size() > 40) spec = spec.substr(0, 40) + "...";
return "generate from spec: " + spec;
}
if (toolName == "whetstone_run_pipeline") {
std::string src = input.value("sourceLanguage", "?");
std::string tgt = input.value("targetLanguage", "?");
return "pipeline " + src + " -> " + tgt;
}
return "call";
}
};

View File

@@ -25,6 +25,28 @@ static void renderAgentChatPanel(EditorState& state) {
chat.autoScroll = false;
ImGui::EndChild();
if (!chat.toolCalls.empty()) {
ImGui::Separator();
ImGui::TextUnformatted("Tool Calls");
for (std::size_t i = 0; i < chat.toolCalls.size(); ++i) {
auto& call = chat.toolCalls[i];
std::string label = AgentToolCallVisualization::inlineLabel(call);
if (ImGui::CollapsingHeader((label + "##tool_" + std::to_string(i)).c_str())) {
call.expanded = true;
ImGui::TextUnformatted("Input");
ImGui::BeginChild(("##tool_in_" + std::to_string(i)).c_str(), ImVec2(-1, 70), true);
ImGui::TextUnformatted(call.inputJson.c_str());
ImGui::EndChild();
ImGui::TextUnformatted("Output");
ImGui::BeginChild(("##tool_out_" + std::to_string(i)).c_str(), ImVec2(-1, 70), true);
ImGui::TextUnformatted(call.outputJson.c_str());
ImGui::EndChild();
} else {
call.expanded = false;
}
}
}
ImGuiInputTextFlags flags = ImGuiInputTextFlags_AllowTabInput;
InputTextMultilineStr("##AgentChatInput", &chat.draftInput, ImVec2(-90, 80), flags);
ImGui::SameLine();