Add step 625 tool call visualization model
This commit is contained in:
@@ -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";
|
||||
|
||||
63
editor/src/AgentToolCallVisualization.h
Normal file
63
editor/src/AgentToolCallVisualization.h
Normal 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";
|
||||
}
|
||||
};
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user