aissia/src/shared/tools/InternalTools.cpp
StillHammer d17ee5fbdc feat: AISSIA rename and codebase updates
- Renamed project from Celuna to AISSIA
- Updated all documentation and configuration files
- Codebase improvements and fixes

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-03 18:37:13 +07:00

413 lines
13 KiB
C++

#include "InternalTools.hpp"
#include <spdlog/sinks/stdout_color_sinks.h>
namespace celuna {
InternalTools::InternalTools(grove::IIO* io) : m_io(io) {
m_logger = spdlog::get("InternalTools");
if (!m_logger) {
m_logger = spdlog::stdout_color_mt("InternalTools");
}
m_bridge = std::make_unique<IOBridge>(io);
m_bridge->subscribeToResponses();
registerTools();
m_logger->info("InternalTools initialized with {} tools", m_tools.size());
}
void InternalTools::registerTools() {
// ========================================================================
// SCHEDULER TOOLS
// ========================================================================
m_tools.push_back({
"get_current_task",
"Get the task currently being worked on. Returns task name, duration, and status.",
{
{"type", "object"},
{"properties", json::object()},
{"required", json::array()}
},
[this](const json& input) { return getCurrentTask(input); }
});
m_tools.push_back({
"list_tasks",
"List all planned tasks for today. Returns task names, estimated durations, and completion status.",
{
{"type", "object"},
{"properties", {
{"include_completed", {
{"type", "boolean"},
{"description", "Whether to include completed tasks"},
{"default", false}
}}
}},
{"required", json::array()}
},
[this](const json& input) { return listTasks(input); }
});
m_tools.push_back({
"start_task",
"Start working on a specific task by its ID or name.",
{
{"type", "object"},
{"properties", {
{"task_id", {
{"type", "string"},
{"description", "Task ID or name to start"}
}}
}},
{"required", {"task_id"}}
},
[this](const json& input) { return startTask(input); }
});
m_tools.push_back({
"complete_task",
"Mark the current task or a specific task as completed.",
{
{"type", "object"},
{"properties", {
{"task_id", {
{"type", "string"},
{"description", "Task ID to complete. If not provided, completes current task."}
}}
}},
{"required", json::array()}
},
[this](const json& input) { return completeTask(input); }
});
m_tools.push_back({
"start_break",
"Start a break period. The user will be reminded when break is over.",
{
{"type", "object"},
{"properties", {
{"duration_minutes", {
{"type", "integer"},
{"description", "Break duration in minutes"},
{"default", 10}
}},
{"reason", {
{"type", "string"},
{"description", "Reason for break (coffee, stretch, etc.)"}
}}
}},
{"required", json::array()}
},
[this](const json& input) { return startBreak(input); }
});
// ========================================================================
// MONITORING TOOLS
// ========================================================================
m_tools.push_back({
"get_focus_stats",
"Get focus statistics: time spent on productive vs distracting apps, current session duration.",
{
{"type", "object"},
{"properties", {
{"period", {
{"type", "string"},
{"enum", {"today", "week", "month"}},
{"description", "Time period for stats"},
{"default", "today"}
}}
}},
{"required", json::array()}
},
[this](const json& input) { return getFocusStats(input); }
});
m_tools.push_back({
"get_current_app",
"Get the currently active application name and window title.",
{
{"type", "object"},
{"properties", json::object()},
{"required", json::array()}
},
[this](const json& input) { return getCurrentApp(input); }
});
// ========================================================================
// STORAGE TOOLS
// ========================================================================
m_tools.push_back({
"save_note",
"Save a note or reminder for the user. Notes are searchable and timestamped.",
{
{"type", "object"},
{"properties", {
{"content", {
{"type", "string"},
{"description", "Note content to save"}
}},
{"tags", {
{"type", "array"},
{"items", {{"type", "string"}}},
{"description", "Optional tags for categorization"}
}}
}},
{"required", {"content"}}
},
[this](const json& input) { return saveNote(input); }
});
m_tools.push_back({
"query_notes",
"Search through saved notes by keyword or tag.",
{
{"type", "object"},
{"properties", {
{"query", {
{"type", "string"},
{"description", "Search query"}
}},
{"tag", {
{"type", "string"},
{"description", "Filter by tag"}
}},
{"limit", {
{"type", "integer"},
{"description", "Maximum number of notes to return"},
{"default", 10}
}}
}},
{"required", json::array()}
},
[this](const json& input) { return queryNotes(input); }
});
m_tools.push_back({
"get_session_history",
"Get history of work sessions with durations and focus scores.",
{
{"type", "object"},
{"properties", {
{"days", {
{"type", "integer"},
{"description", "Number of days to look back"},
{"default", 7}
}}
}},
{"required", json::array()}
},
[this](const json& input) { return getSessionHistory(input); }
});
// ========================================================================
// VOICE TOOLS
// ========================================================================
m_tools.push_back({
"speak",
"Make the assistant speak a message out loud using text-to-speech.",
{
{"type", "object"},
{"properties", {
{"message", {
{"type", "string"},
{"description", "Message to speak"}
}},
{"priority", {
{"type", "string"},
{"enum", {"low", "normal", "high"}},
{"description", "Speech priority"},
{"default", "normal"}
}}
}},
{"required", {"message"}}
},
[this](const json& input) { return speak(input); }
});
}
std::vector<ToolDefinition> InternalTools::getTools() const {
return m_tools;
}
void InternalTools::processResponses() {
if (!m_io) return;
while (m_io->hasMessages() > 0) {
auto msg = m_io->pullMessage();
// Check if this is a response message
if (msg.topic.find(":response") != std::string::npos && msg.data) {
m_bridge->handleResponse(msg.topic, *msg.data);
}
}
}
// ============================================================================
// TOOL IMPLEMENTATIONS
// ============================================================================
json InternalTools::getCurrentTask(const json& input) {
auto response = m_bridge->request("scheduler:query", {
{"action", "get_current_task"}
});
if (response.contains("error")) {
return response;
}
return {
{"task_id", response.value("task_id", "")},
{"task_name", response.value("task_name", "No active task")},
{"duration_minutes", response.value("duration_minutes", 0)},
{"started_at", response.value("started_at", "")}
};
}
json InternalTools::listTasks(const json& input) {
bool includeCompleted = input.value("include_completed", false);
auto response = m_bridge->request("scheduler:query", {
{"action", "list_tasks"},
{"include_completed", includeCompleted}
});
return response;
}
json InternalTools::startTask(const json& input) {
std::string taskId = input.value("task_id", "");
if (taskId.empty()) {
return {{"error", "missing_parameter"}, {"message", "task_id is required"}};
}
auto response = m_bridge->request("scheduler:command", {
{"action", "start_task"},
{"task_id", taskId}
});
return response;
}
json InternalTools::completeTask(const json& input) {
std::string taskId = input.value("task_id", "");
auto response = m_bridge->request("scheduler:command", {
{"action", "complete_task"},
{"task_id", taskId} // Empty = complete current task
});
return response;
}
json InternalTools::startBreak(const json& input) {
int duration = input.value("duration_minutes", 10);
std::string reason = input.value("reason", "break");
auto response = m_bridge->request("scheduler:command", {
{"action", "start_break"},
{"duration_minutes", duration},
{"reason", reason}
});
return {
{"success", true},
{"message", "Break started for " + std::to_string(duration) + " minutes"},
{"reason", reason}
};
}
json InternalTools::getFocusStats(const json& input) {
std::string period = input.value("period", "today");
auto response = m_bridge->request("monitoring:query", {
{"action", "get_focus_stats"},
{"period", period}
});
return response;
}
json InternalTools::getCurrentApp(const json& input) {
auto response = m_bridge->request("monitoring:query", {
{"action", "get_current_app"}
});
return response;
}
json InternalTools::saveNote(const json& input) {
std::string content = input.value("content", "");
if (content.empty()) {
return {{"error", "missing_parameter"}, {"message", "content is required"}};
}
json tags = input.value("tags", json::array());
auto response = m_bridge->request("storage:command", {
{"action", "save_note"},
{"content", content},
{"tags", tags}
});
return {
{"success", true},
{"message", "Note saved"},
{"note_id", response.value("note_id", "")}
};
}
json InternalTools::queryNotes(const json& input) {
std::string query = input.value("query", "");
std::string tag = input.value("tag", "");
int limit = input.value("limit", 10);
auto response = m_bridge->request("storage:query", {
{"action", "query_notes"},
{"query", query},
{"tag", tag},
{"limit", limit}
});
return response;
}
json InternalTools::getSessionHistory(const json& input) {
int days = input.value("days", 7);
auto response = m_bridge->request("storage:query", {
{"action", "get_session_history"},
{"days", days}
});
return response;
}
json InternalTools::speak(const json& input) {
std::string message = input.value("message", "");
if (message.empty()) {
return {{"error", "missing_parameter"}, {"message", "message is required"}};
}
std::string priority = input.value("priority", "normal");
// For speak, we don't wait for response - it's fire and forget
auto requestNode = std::make_unique<grove::JsonDataNode>("request");
requestNode->setString("action", "speak");
requestNode->setString("text", message);
requestNode->setString("priority", priority);
m_io->publish("voice:command", std::move(requestNode));
return {
{"success", true},
{"message", "Speech queued"}
};
}
} // namespace celuna