feat: replace logging with custom log_all function and truncate benchmark log on start
This commit is contained in:
@@ -98,6 +98,9 @@ static char *agent_build_request(agent_handle agent, const char *role, const cha
|
||||
json_object_new_int(r_config_get_max_tokens(cfg)));
|
||||
|
||||
char *result = strdup(json_object_to_json_string_ext(root, JSON_C_TO_STRING_PRETTY));
|
||||
if (agent->verbose && !agent->is_subagent) {
|
||||
fprintf(stderr, "\n[LLM Request]\n%s\n", result);
|
||||
}
|
||||
json_object_put(root);
|
||||
return result;
|
||||
}
|
||||
@@ -112,6 +115,10 @@ static struct json_object *agent_process_response(agent_handle agent, const char
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (agent->verbose && !agent->is_subagent) {
|
||||
fprintf(stderr, "\n[LLM Response]\n%s\n", response);
|
||||
}
|
||||
|
||||
struct json_object *parsed = json_tokener_parse(response);
|
||||
free(response);
|
||||
|
||||
|
||||
+54
-54
@@ -13,9 +13,22 @@ static const char *get_message_role(struct json_object *msg) {
|
||||
if (json_object_object_get_ex(msg, "role", &role_obj)) {
|
||||
return json_object_get_string(role_obj);
|
||||
}
|
||||
// Tool results don't have a 'role' field in some implementations,
|
||||
// they have 'tool_call_id'.
|
||||
if (json_object_object_get_ex(msg, "tool_call_id", &role_obj)) {
|
||||
return "tool";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
static bool has_tool_calls(struct json_object *msg) {
|
||||
struct json_object *tool_calls;
|
||||
if (json_object_object_get_ex(msg, "tool_calls", &tool_calls)) {
|
||||
return json_object_array_length(tool_calls) > 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static size_t get_message_content_len(struct json_object *msg) {
|
||||
struct json_object *content_obj;
|
||||
const char *content = NULL;
|
||||
@@ -70,7 +83,7 @@ static r_status_t perform_truncate(messages_handle msgs, int index, double ratio
|
||||
strcat(new_content, TRUNCATE_MARKER);
|
||||
strcat(new_content, content + len - keep_each);
|
||||
|
||||
struct json_object *new_msg = json_object_get(msg);
|
||||
struct json_object *new_msg = json_tokener_parse(json_object_to_json_string(msg));
|
||||
if (is_tool_result) {
|
||||
json_object_object_add(new_msg, "tool_result", json_object_new_string(new_content));
|
||||
} else {
|
||||
@@ -85,71 +98,58 @@ r_status_t context_manager_shrink(messages_handle msgs) {
|
||||
if (!msgs) return R_ERROR_INVALID_ARG;
|
||||
|
||||
int count = messages_count(msgs);
|
||||
if (count <= 1) return R_ERROR_API_ERROR;
|
||||
if (count <= 2) return R_ERROR_API_ERROR;
|
||||
|
||||
size_t initial_size = calculate_total_size(msgs);
|
||||
// Target 40% of initial size to be safe and avoid immediate re-overflow
|
||||
size_t target_size = (size_t)(initial_size * 0.4);
|
||||
if (target_size < 10000) target_size = 10000; // Don't shrink too much if it's already small
|
||||
size_t target_size = (size_t)(initial_size * 0.5);
|
||||
if (target_size < 20000) target_size = 20000;
|
||||
|
||||
fprintf(stderr, " \033[2m-> Context overflow (approx %zu chars). Shrinking to %zu...\033[0m\n",
|
||||
fprintf(stderr, " \033[2m-> Context overflow (%zu chars). Middle-out shrinking to %zu...\033[0m\n",
|
||||
initial_size, target_size);
|
||||
|
||||
int iterations = 0;
|
||||
while (calculate_total_size(msgs) > target_size && iterations < 50) {
|
||||
iterations++;
|
||||
count = messages_count(msgs);
|
||||
|
||||
// Strategy 1: Find largest non-system, non-last message and truncate it
|
||||
int largest_idx = -1;
|
||||
size_t largest_size = 0;
|
||||
|
||||
for (int i = 0; i < count - 1; i++) {
|
||||
struct json_object *msg = messages_get_object(msgs, i);
|
||||
if (strcmp(get_message_role(msg), "system") == 0) continue;
|
||||
|
||||
size_t s = get_message_content_len(msg);
|
||||
if (s > largest_size) {
|
||||
largest_size = s;
|
||||
largest_idx = i;
|
||||
// Strategy 1: Truncate very large messages first (safe, doesn't break sequence)
|
||||
for (int i = 0; i < messages_count(msgs); i++) {
|
||||
struct json_object *msg = messages_get_object(msgs, i);
|
||||
if (get_message_content_len(msg) > 50000) {
|
||||
perform_truncate(msgs, i, 0.2);
|
||||
}
|
||||
}
|
||||
|
||||
// Strategy 2: Remove messages from the middle until size is within target
|
||||
// We keep:
|
||||
// - System message (usually index 0)
|
||||
// - Most recent 4 messages (usually current task context)
|
||||
while (calculate_total_size(msgs) > target_size && messages_count(msgs) > 6) {
|
||||
int middle_idx = 1; // Start after system
|
||||
struct json_object *msg = messages_get_object(msgs, middle_idx);
|
||||
const char *role = get_message_role(msg);
|
||||
|
||||
int remove_count = 1;
|
||||
if (strcmp(role, "assistant") == 0 && has_tool_calls(msg)) {
|
||||
// Must also remove the following tool results to maintain sequence
|
||||
int search_idx = middle_idx + 1;
|
||||
while (search_idx < messages_count(msgs) - 4) {
|
||||
struct json_object *next_msg = messages_get_object(msgs, search_idx);
|
||||
if (strcmp(get_message_role(next_msg), "tool") == 0) {
|
||||
remove_count++;
|
||||
search_idx++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (largest_idx != -1 && largest_size > 1000) {
|
||||
perform_truncate(msgs, largest_idx, 0.3); // Cut to 30% of its size
|
||||
continue;
|
||||
}
|
||||
|
||||
// Strategy 2: Remove oldest removable messages (keep sequence)
|
||||
int first_removable = -1;
|
||||
for (int i = 0; i < count - 1; i++) {
|
||||
struct json_object *msg = messages_get_object(msgs, i);
|
||||
if (strcmp(get_message_role(msg), "system") != 0) {
|
||||
first_removable = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (first_removable != -1 && first_removable < count - 1) {
|
||||
// Remove 1 message at a time from the front
|
||||
messages_remove_range(msgs, first_removable, 1);
|
||||
} else {
|
||||
// Nothing left to remove but system or last message
|
||||
// Ensure we don't eat into the "recent" buffer
|
||||
if (middle_idx + remove_count > messages_count(msgs) - 4) {
|
||||
break;
|
||||
}
|
||||
|
||||
messages_remove_range(msgs, middle_idx, remove_count);
|
||||
}
|
||||
|
||||
// Last Resort: If still too big, truncate the last message
|
||||
size_t final_size = calculate_total_size(msgs);
|
||||
if (final_size > target_size) {
|
||||
count = messages_count(msgs);
|
||||
if (count > 0) {
|
||||
perform_truncate(msgs, count - 1, 0.5);
|
||||
}
|
||||
}
|
||||
|
||||
size_t shrunk_size = calculate_total_size(msgs);
|
||||
fprintf(stderr, " \033[2m-> Context shrunk to approx %zu chars.\033[0m\n", shrunk_size);
|
||||
fprintf(stderr, " \033[2m-> Context shrunk to %zu chars. Remaining messages: %d\033[0m\n",
|
||||
final_size, messages_count(msgs));
|
||||
|
||||
return R_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
+34
-14
@@ -252,7 +252,8 @@ static void repl(void) {
|
||||
while (line && *line != '\n') {
|
||||
char *response = agent_chat(line, global_messages);
|
||||
if (response) {
|
||||
// response is already printed inside agent_run via parse_markdown_to_ansi
|
||||
// response is already printed inside agent_run via
|
||||
// parse_markdown_to_ansi
|
||||
free(response);
|
||||
} else {
|
||||
fprintf(stderr, "Agent returned no response\n");
|
||||
@@ -294,24 +295,43 @@ static void init(void) {
|
||||
"until the goal is achieved.\n\n"
|
||||
"## Reasoning Pattern (ReAct)\n"
|
||||
"For EVERY task, you MUST follow this sequence:\n"
|
||||
"1. Plan: Break the task into logical sub-tasks. Decide which specialized agents to spawn.\n"
|
||||
"2. Execute: Spawn agents or use tools. INTEGRATE their results immediately.\n"
|
||||
"3. Verify: Ensure the integrated results meet the goal. Perform any final actions (like saving to a file).\n"
|
||||
"4. Conclude: Only after ALL sub-tasks and final actions are done, provide your final response.\n\n"
|
||||
"1. Plan: Break the task into logical sub-tasks. Decide which "
|
||||
"specialized agents to spawn.\n"
|
||||
"2. Execute: Spawn agents or use tools. INTEGRATE their results "
|
||||
"immediately.\n"
|
||||
"3. Verify: Ensure the integrated results meet the goal. Perform any "
|
||||
"final actions (like saving to a file).\n"
|
||||
"4. Conclude: Only after ALL sub-tasks and final actions are done, "
|
||||
"provide your final response.\n\n"
|
||||
"## Multi-Agent Orchestration (MANDATORY)\n"
|
||||
"You are the Lead Orchestrator. You MUST delegate specialized work:\n"
|
||||
"- researcher: For ALL information gathering. Never research yourself if you can spawn a researcher.\n"
|
||||
"- researcher: For ALL information gathering. Never research yourself if "
|
||||
"you can spawn a researcher.\n"
|
||||
"- developer: For ALL coding, testing, and debugging.\n"
|
||||
"- security: For ALL security-related audits.\n\n"
|
||||
"IMPORTANT: When a sub-agent returns a result, you MUST read it, synthesize it, and then perform any necessary follow-up actions (like writing to a file or spawning another agent). NEVER assume a task is done just because a sub-agent finished; YOU must complete the final delivery.\n\n"
|
||||
"MANDATORY FINAL ACTION: If the user asked to save results to a file, YOU must call the write_file tool yourself with the synthesized data from the sub-agent. Do not ask for permission.\n\n"
|
||||
"IMPORTANT: When a sub-agent returns a result, you MUST read it, "
|
||||
"synthesize it, and then perform any necessary follow-up actions (like "
|
||||
"writing to a file or spawning another agent). NEVER assume a task is "
|
||||
"done just because a sub-agent finished; YOU must complete the final "
|
||||
"delivery.\n\n"
|
||||
"MANDATORY FINAL ACTION: If the user asked to save results to a file, "
|
||||
"YOU must call the write_file tool yourself with the synthesized data "
|
||||
"from the sub-agent. Do not ask for permission.\n\n"
|
||||
"## Tool Usage\n"
|
||||
"- Use tools proactively. If you say you will do something, you MUST call the tool in the SAME or NEXT turn.\n"
|
||||
"- Use tools proactively. If you say you will do something, you MUST "
|
||||
"call the tool in the SAME or NEXT turn.\n"
|
||||
"- If a tool fails, analyze and retry with a different approach.\n\n"
|
||||
"## CRITICAL OUTPUT RULES\n"
|
||||
"- SHOW THE DATA: Always include the actual content from tool/agent results in your response.\n"
|
||||
"- NO PREMATURE COMPLETION: Do not say 'task complete' until you have verified all files are written and all steps are finished.\n"
|
||||
"- SEQUENTIAL EXECUTION: Perform one logical step at a time. If you need to research AND write a file, spawn the researcher first, wait for the result, THEN write the file.\n"
|
||||
"- SHOW THE DATA: Always include the actual content from tool/agent "
|
||||
"results in your response.\n"
|
||||
"- NO PREMATURE COMPLETION: Do not say 'task complete' until you have "
|
||||
"verified all files are written and all steps are finished.\n"
|
||||
"- SEQUENTIAL EXECUTION: Perform one logical step at a time. If you need "
|
||||
"to research AND write a file, spawn the researcher first, wait for the "
|
||||
"result, THEN write the file.\n"
|
||||
"## EXECUTION OF PYTHON CODE\n"
|
||||
"Exclusively use native python without 3rd party packages unless you "
|
||||
"have checked that they're installed on the system.\n"
|
||||
"## Local Database\n"
|
||||
"You have a local SQLite database accessible via db_query, db_get, and "
|
||||
"db_set tools.\n"
|
||||
@@ -339,8 +359,8 @@ static void init(void) {
|
||||
"Prefer commands that do not require root access.\n"
|
||||
"## COMMUNICATION\n"
|
||||
"You are only allowed to talk once, so do that absolutely last with your "
|
||||
"conclusion.\n", datetime,
|
||||
cwd, schema ? schema : "{}");
|
||||
"conclusion.\n",
|
||||
datetime, cwd, schema ? schema : "{}");
|
||||
free(schema);
|
||||
fprintf(stderr, "Loading...");
|
||||
|
||||
|
||||
@@ -36,11 +36,18 @@ static struct json_object *tool_spawn_agent_get_description(void) {
|
||||
json_object_object_add(max_subagents, "description", json_object_new_string("Remaining budget for spawning recursive sub-agents. Decrement this by 1 when spawning a sub-agent. Default is 2."));
|
||||
json_object_object_add(max_subagents, "default", json_object_new_int(2));
|
||||
json_object_object_add(props, "max_subagents", max_subagents);
|
||||
|
||||
struct json_object *as = json_object_new_object();
|
||||
json_object_object_add(as, "type", json_object_new_string("boolean"));
|
||||
json_object_object_add(as, "description", json_object_new_string("Required for strict mode."));
|
||||
json_object_object_add(props, "async", as);
|
||||
|
||||
json_object_object_add(params, "properties", props);
|
||||
struct json_object *required = json_object_new_array();
|
||||
json_object_array_add(required, json_object_new_string("persona"));
|
||||
json_object_array_add(required, json_object_new_string("goal"));
|
||||
json_object_array_add(required, json_object_new_string("max_subagents"));
|
||||
json_object_array_add(required, json_object_new_string("async"));
|
||||
json_object_object_add(params, "required", required);
|
||||
json_object_object_add(params, "additionalProperties", json_object_new_boolean(0));
|
||||
json_object_object_add(obj, "parameters", params);
|
||||
|
||||
+48
-32
@@ -21,34 +21,35 @@ tool_t *tool_csv_export_create(void) { return &csv_export_tool; }
|
||||
|
||||
static char *csv_export_execute(tool_t *self, struct json_object *args) {
|
||||
(void)self;
|
||||
struct json_object *path_obj, *data_obj;
|
||||
struct json_object *path_obj, *headers_obj, *rows_obj;
|
||||
if (!json_object_object_get_ex(args, "path", &path_obj) ||
|
||||
!json_object_object_get_ex(args, "data", &data_obj)) {
|
||||
return strdup("Error: path and data required");
|
||||
!json_object_object_get_ex(args, "headers", &headers_obj) ||
|
||||
!json_object_object_get_ex(args, "rows", &rows_obj)) {
|
||||
return strdup("Error: path, headers, and rows required");
|
||||
}
|
||||
|
||||
const char *path = json_object_get_string(path_obj);
|
||||
FILE *fp = fopen(path, "w");
|
||||
if (!fp) return strdup("Error: could not open file for writing");
|
||||
|
||||
int row_count = json_object_array_length(data_obj);
|
||||
// Write headers
|
||||
int header_count = json_object_array_length(headers_obj);
|
||||
for (int i = 0; i < header_count; i++) {
|
||||
fprintf(fp, "%s%s", json_object_get_string(json_object_array_get_idx(headers_obj, i)),
|
||||
(i == header_count - 1) ? "" : ",");
|
||||
}
|
||||
fprintf(fp, "\n");
|
||||
|
||||
// Write rows
|
||||
int row_count = json_object_array_length(rows_obj);
|
||||
for (int i = 0; i < row_count; i++) {
|
||||
struct json_object *row = json_object_array_get_idx(data_obj, i);
|
||||
if (json_object_get_type(row) == json_type_object) {
|
||||
// Use keys as header if first row
|
||||
if (i == 0) {
|
||||
json_object_object_foreach(row, key, val) {
|
||||
(void)val;
|
||||
fprintf(fp, "%s,", key);
|
||||
}
|
||||
fprintf(fp, "\n");
|
||||
}
|
||||
json_object_object_foreach(row, key2, val2) {
|
||||
(void)key2;
|
||||
fprintf(fp, "\"%s\",", json_object_get_string(val2));
|
||||
}
|
||||
fprintf(fp, "\n");
|
||||
struct json_object *row = json_object_array_get_idx(rows_obj, i);
|
||||
int col_count = json_object_array_length(row);
|
||||
for (int j = 0; j < col_count; j++) {
|
||||
fprintf(fp, "\"%s\"%s", json_object_get_string(json_object_array_get_idx(row, j)),
|
||||
(j == col_count - 1) ? "" : ",");
|
||||
}
|
||||
fprintf(fp, "\n");
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
@@ -60,28 +61,43 @@ static struct json_object *csv_export_get_description(void) {
|
||||
json_object_object_add(root, "type", json_object_new_string("function"));
|
||||
struct json_object *function = json_object_new_object();
|
||||
json_object_object_add(function, "name", json_object_new_string("csv_export"));
|
||||
json_object_object_add(function, "description", json_object_new_string("Exports an array of JSON objects to a CSV file."));
|
||||
json_object_object_add(function, "description", json_object_new_string("Exports headers and rows to a CSV file."));
|
||||
|
||||
struct json_object *parameters = json_object_new_object();
|
||||
json_object_object_add(parameters, "type", json_object_new_string("object"));
|
||||
|
||||
struct json_object *properties = json_object_new_object();
|
||||
|
||||
// Path
|
||||
struct json_object *path = json_object_new_object();
|
||||
json_object_object_add(path, "type", json_object_new_string("string"));
|
||||
json_object_object_add(properties, "path", path);
|
||||
struct json_object *data = json_object_new_object();
|
||||
json_object_object_add(data, "type", json_object_new_string("array"));
|
||||
struct json_object *items = json_object_new_object();
|
||||
json_object_object_add(items, "type", json_object_new_string("object"));
|
||||
struct json_object *item_props = json_object_new_object();
|
||||
json_object_object_add(items, "properties", item_props);
|
||||
json_object_object_add(items, "required", json_object_new_array()); // Allow empty objects or define later if known
|
||||
json_object_object_add(items, "additionalProperties", json_object_new_boolean(0));
|
||||
json_object_object_add(data, "items", items);
|
||||
json_object_object_add(properties, "data", data);
|
||||
|
||||
// Headers
|
||||
struct json_object *headers = json_object_new_object();
|
||||
json_object_object_add(headers, "type", json_object_new_string("array"));
|
||||
struct json_object *h_items = json_object_new_object();
|
||||
json_object_object_add(h_items, "type", json_object_new_string("string"));
|
||||
json_object_object_add(headers, "items", h_items);
|
||||
json_object_object_add(properties, "headers", headers);
|
||||
|
||||
// Rows
|
||||
struct json_object *rows = json_object_new_object();
|
||||
json_object_object_add(rows, "type", json_object_new_string("array"));
|
||||
struct json_object *r_items = json_object_new_object();
|
||||
json_object_object_add(r_items, "type", json_object_new_string("array"));
|
||||
struct json_object *r_inner_items = json_object_new_object();
|
||||
json_object_object_add(r_inner_items, "type", json_object_new_string("string"));
|
||||
json_object_object_add(r_items, "items", r_inner_items);
|
||||
json_object_object_add(rows, "items", r_items);
|
||||
json_object_object_add(properties, "rows", rows);
|
||||
|
||||
json_object_object_add(parameters, "properties", properties);
|
||||
|
||||
struct json_object *required = json_object_new_array();
|
||||
json_object_array_add(required, json_object_new_string("path"));
|
||||
json_object_array_add(required, json_object_new_string("data"));
|
||||
json_object_array_add(required, json_object_new_string("headers"));
|
||||
json_object_array_add(required, json_object_new_string("rows"));
|
||||
json_object_object_add(parameters, "required", required);
|
||||
json_object_object_add(parameters, "additionalProperties", json_object_new_boolean(0));
|
||||
|
||||
@@ -94,4 +110,4 @@ static struct json_object *csv_export_get_description(void) {
|
||||
|
||||
json_object_object_add(root, "function", function);
|
||||
return root;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-151
@@ -15,37 +15,15 @@ static struct json_object *python_execute_get_description(void);
|
||||
static char *python_execute_execute(tool_t *self, struct json_object *args);
|
||||
static void python_execute_print_action(const char *name, struct json_object *args);
|
||||
|
||||
static struct json_object *python_status_get_description(void);
|
||||
static char *python_status_execute(tool_t *self, struct json_object *args);
|
||||
|
||||
static struct json_object *python_terminate_get_description(void);
|
||||
static char *python_terminate_execute(tool_t *self, struct json_object *args);
|
||||
|
||||
static const tool_vtable_t python_execute_vtable = {
|
||||
.get_description = python_execute_get_description,
|
||||
.execute = python_execute_execute,
|
||||
.print_action = python_execute_print_action
|
||||
};
|
||||
|
||||
static const tool_vtable_t python_status_vtable = {
|
||||
.get_description = python_status_get_description,
|
||||
.execute = python_status_execute,
|
||||
.print_action = NULL
|
||||
};
|
||||
|
||||
static const tool_vtable_t python_terminate_vtable = {
|
||||
.get_description = python_terminate_get_description,
|
||||
.execute = python_terminate_execute,
|
||||
.print_action = NULL
|
||||
};
|
||||
|
||||
static tool_t python_execute_tool = { .vtable = &python_execute_vtable, .name = "python_execute" };
|
||||
static tool_t python_status_tool = { .vtable = &python_status_vtable, .name = "python_get_status" };
|
||||
static tool_t python_terminate_tool = { .vtable = &python_terminate_vtable, .name = "python_terminate" };
|
||||
|
||||
tool_t *tool_python_execute_create(void) { return &python_execute_tool; }
|
||||
tool_t *tool_python_get_status_create(void) { return &python_status_tool; }
|
||||
tool_t *tool_python_terminate_create(void) { return &python_terminate_tool; }
|
||||
|
||||
static void python_execute_print_action(const char *name, struct json_object *args) {
|
||||
(void)name;
|
||||
@@ -110,86 +88,6 @@ static char *python_execute_execute(tool_t *self, struct json_object *args) {
|
||||
return out_str;
|
||||
}
|
||||
|
||||
static char *python_status_execute(tool_t *self, struct json_object *args) {
|
||||
(void)self;
|
||||
struct json_object *pid_obj;
|
||||
if (!json_object_object_get_ex(args, "pid", &pid_obj)) return strdup("Error: missing 'pid'");
|
||||
int pid = json_object_get_int(pid_obj);
|
||||
|
||||
int status;
|
||||
bool running = true;
|
||||
int exit_status = -1;
|
||||
|
||||
pid_t ret = waitpid(pid, &status, WNOHANG);
|
||||
if (ret == pid) {
|
||||
running = false;
|
||||
exit_status = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
|
||||
} else if (ret == -1) {
|
||||
running = (kill(pid, 0) == 0);
|
||||
}
|
||||
|
||||
char log_path[256];
|
||||
snprintf(log_path, sizeof(log_path), "/tmp/r_process_%d.log", pid);
|
||||
|
||||
char *content = NULL;
|
||||
FILE *f = fopen(log_path, "r");
|
||||
if (f) {
|
||||
fseek(f, 0, SEEK_END);
|
||||
long size = ftell(f);
|
||||
rewind(f);
|
||||
if (size >= 0) {
|
||||
content = malloc((size_t)size + 1);
|
||||
if (content) {
|
||||
size_t rs = fread(content, 1, (size_t)size, f);
|
||||
content[rs] = '\0';
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
struct json_object *root = json_object_new_object();
|
||||
json_object_object_add(root, "pid", json_object_new_int(pid));
|
||||
json_object_object_add(root, "is_running", json_object_new_boolean(running));
|
||||
json_object_object_add(root, "output", json_object_new_string(content ? content : ""));
|
||||
if (!running) {
|
||||
json_object_object_add(root, "exit_status", json_object_new_int(exit_status));
|
||||
}
|
||||
|
||||
if (content && *content) {
|
||||
char *copy = strdup(content);
|
||||
char *saveptr;
|
||||
char *line = strtok_r(copy, "\n", &saveptr);
|
||||
while (line) {
|
||||
fprintf(stdout, "[%d]\t %s\n", pid, line);
|
||||
line = strtok_r(NULL, "\n", &saveptr);
|
||||
}
|
||||
fflush(stdout);
|
||||
free(copy);
|
||||
}
|
||||
|
||||
char *out_str = strdup(json_object_to_json_string_ext(root, JSON_C_TO_STRING_PRETTY));
|
||||
json_object_put(root);
|
||||
free(content);
|
||||
return out_str;
|
||||
}
|
||||
|
||||
static char *python_terminate_execute(tool_t *self, struct json_object *args) {
|
||||
(void)self;
|
||||
struct json_object *pid_obj;
|
||||
if (!json_object_object_get_ex(args, "pid", &pid_obj)) return strdup("Error: missing 'pid'");
|
||||
int pid = json_object_get_int(pid_obj);
|
||||
|
||||
kill(pid, SIGTERM);
|
||||
usleep(100000);
|
||||
if (kill(pid, 0) == 0) kill(pid, SIGKILL);
|
||||
|
||||
char log_path[256];
|
||||
snprintf(log_path, sizeof(log_path), "/tmp/r_process_%d.log", pid);
|
||||
unlink(log_path);
|
||||
|
||||
return strdup("Python process terminated and logs cleaned up.");
|
||||
}
|
||||
|
||||
static struct json_object *python_execute_get_description(void) {
|
||||
struct json_object *root = json_object_new_object();
|
||||
json_object_object_add(root, "type", json_object_new_string("function"));
|
||||
@@ -225,52 +123,4 @@ static struct json_object *python_execute_get_description(void) {
|
||||
if (r_config_use_strict(cfg)) json_object_object_add(f, "strict", json_object_new_boolean(1));
|
||||
json_object_object_add(root, "function", f);
|
||||
return root;
|
||||
}
|
||||
|
||||
static struct json_object *python_status_get_description(void) {
|
||||
struct json_object *root = json_object_new_object();
|
||||
json_object_object_add(root, "type", json_object_new_string("function"));
|
||||
struct json_object *f = json_object_new_object();
|
||||
json_object_object_add(f, "name", json_object_new_string("python_get_status"));
|
||||
json_object_object_add(f, "description", json_object_new_string("Get status and logs of a background Python process by PID."));
|
||||
struct json_object *p = json_object_new_object();
|
||||
json_object_object_add(p, "type", json_object_new_string("object"));
|
||||
struct json_object *props = json_object_new_object();
|
||||
struct json_object *pid = json_object_new_object();
|
||||
json_object_object_add(pid, "type", json_object_new_string("integer"));
|
||||
json_object_object_add(props, "pid", pid);
|
||||
json_object_object_add(p, "properties", props);
|
||||
struct json_object *req = json_object_new_array();
|
||||
json_object_array_add(req, json_object_new_string("pid"));
|
||||
json_object_object_add(p, "required", req);
|
||||
json_object_object_add(p, "additionalProperties", json_object_new_boolean(0));
|
||||
json_object_object_add(f, "parameters", p);
|
||||
r_config_handle cfg = r_config_get_instance();
|
||||
if (r_config_use_strict(cfg)) json_object_object_add(f, "strict", json_object_new_boolean(1));
|
||||
json_object_object_add(root, "function", f);
|
||||
return root;
|
||||
}
|
||||
|
||||
static struct json_object *python_terminate_get_description(void) {
|
||||
struct json_object *root = json_object_new_object();
|
||||
json_object_object_add(root, "type", json_object_new_string("function"));
|
||||
struct json_object *f = json_object_new_object();
|
||||
json_object_object_add(f, "name", json_object_new_string("python_terminate"));
|
||||
json_object_object_add(f, "description", json_object_new_string("Terminate a background Python process and clean up."));
|
||||
struct json_object *p = json_object_new_object();
|
||||
json_object_object_add(p, "type", json_object_new_string("object"));
|
||||
struct json_object *props = json_object_new_object();
|
||||
struct json_object *pid = json_object_new_object();
|
||||
json_object_object_add(pid, "type", json_object_new_string("integer"));
|
||||
json_object_object_add(props, "pid", pid);
|
||||
json_object_object_add(p, "properties", props);
|
||||
struct json_object *req = json_object_new_array();
|
||||
json_object_array_add(req, json_object_new_string("pid"));
|
||||
json_object_object_add(p, "required", req);
|
||||
json_object_object_add(p, "additionalProperties", json_object_new_boolean(0));
|
||||
json_object_object_add(f, "parameters", p);
|
||||
r_config_handle cfg = r_config_get_instance();
|
||||
if (r_config_use_strict(cfg)) json_object_object_add(f, "strict", json_object_new_boolean(1));
|
||||
json_object_object_add(root, "function", f);
|
||||
return root;
|
||||
}
|
||||
}
|
||||
+191
-10
@@ -6,20 +6,45 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
static struct json_object *process_monitor_get_description(void);
|
||||
static char *process_monitor_execute(tool_t *self, struct json_object *args);
|
||||
static void process_monitor_print_action(const char *name, struct json_object *args);
|
||||
|
||||
static struct json_object *process_status_get_description(void);
|
||||
static char *process_status_execute(tool_t *self, struct json_object *args);
|
||||
|
||||
static struct json_object *process_terminate_get_description(void);
|
||||
static char *process_terminate_execute(tool_t *self, struct json_object *args);
|
||||
|
||||
static const tool_vtable_t process_monitor_vtable = {
|
||||
.get_description = process_monitor_get_description,
|
||||
.execute = process_monitor_execute,
|
||||
.print_action = process_monitor_print_action
|
||||
};
|
||||
|
||||
static const tool_vtable_t process_status_vtable = {
|
||||
.get_description = process_status_get_description,
|
||||
.execute = process_status_execute,
|
||||
.print_action = NULL
|
||||
};
|
||||
|
||||
static const tool_vtable_t process_terminate_vtable = {
|
||||
.get_description = process_terminate_get_description,
|
||||
.execute = process_terminate_execute,
|
||||
.print_action = NULL
|
||||
};
|
||||
|
||||
static tool_t process_monitor_tool = { .vtable = &process_monitor_vtable, .name = "process_monitor" };
|
||||
static tool_t process_status_tool = { .vtable = &process_status_vtable, .name = "process_get_status" };
|
||||
static tool_t process_terminate_tool = { .vtable = &process_terminate_vtable, .name = "process_terminate" };
|
||||
|
||||
tool_t *tool_process_monitor_create(void) { return &process_monitor_tool; }
|
||||
tool_t *tool_process_get_status_create(void) { return &process_status_tool; }
|
||||
tool_t *tool_process_terminate_create(void) { return &process_terminate_tool; }
|
||||
|
||||
static void process_monitor_print_action(const char *name, struct json_object *args) {
|
||||
(void)name;
|
||||
@@ -38,54 +63,210 @@ static char *process_monitor_execute(tool_t *self, struct json_object *args) {
|
||||
const char *action = json_object_get_string(action_obj);
|
||||
|
||||
if (strcmp(action, "list") == 0) {
|
||||
return r_bash_execute("ps aux | head -n 50", false, 300);
|
||||
struct json_object *filter_obj;
|
||||
if (json_object_object_get_ex(args, "filter", &filter_obj)) {
|
||||
char cmd[512];
|
||||
snprintf(cmd, sizeof(cmd), "ps aux | grep -i '%s' | grep -v grep", json_object_get_string(filter_obj));
|
||||
return r_bash_execute(cmd, false, 300);
|
||||
}
|
||||
return r_bash_execute("ps aux --sort=-%cpu | head -n 20", false, 300);
|
||||
} else if (strcmp(action, "kill") == 0) {
|
||||
struct json_object *pid_obj;
|
||||
if (!json_object_object_get_ex(args, "pid", &pid_obj)) {
|
||||
return strdup("Error: missing 'pid' for kill action");
|
||||
}
|
||||
char cmd[256];
|
||||
snprintf(cmd, sizeof(cmd), "kill -9 %d", json_object_get_int(pid_obj));
|
||||
snprintf(cmd, sizeof(cmd), "kill -9 %d 2>&1", json_object_get_int(pid_obj));
|
||||
return r_bash_execute(cmd, false, 300);
|
||||
}
|
||||
|
||||
return strdup("Error: unknown action");
|
||||
}
|
||||
|
||||
static char *process_status_execute(tool_t *self, struct json_object *args) {
|
||||
(void)self;
|
||||
struct json_object *pid_obj;
|
||||
if (!json_object_object_get_ex(args, "pid", &pid_obj)) return strdup("Error: missing 'pid'");
|
||||
int pid = json_object_get_int(pid_obj);
|
||||
|
||||
int status;
|
||||
bool running = true;
|
||||
int exit_status = -1;
|
||||
|
||||
pid_t ret = waitpid(pid, &status, WNOHANG);
|
||||
if (ret == pid) {
|
||||
running = false;
|
||||
exit_status = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
|
||||
} else if (ret == -1) {
|
||||
running = (kill(pid, 0) == 0);
|
||||
}
|
||||
|
||||
char log_path[256];
|
||||
snprintf(log_path, sizeof(log_path), "/tmp/r_process_%d.log", pid);
|
||||
|
||||
char *content = NULL;
|
||||
FILE *f = fopen(log_path, "r");
|
||||
if (f) {
|
||||
fseek(f, 0, SEEK_END);
|
||||
long size = ftell(f);
|
||||
rewind(f);
|
||||
if (size >= 0) {
|
||||
content = malloc((size_t)size + 1);
|
||||
if (content) {
|
||||
size_t rs = fread(content, 1, (size_t)size, f);
|
||||
content[rs] = '\0';
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
struct json_object *root = json_object_new_object();
|
||||
json_object_object_add(root, "pid", json_object_new_int(pid));
|
||||
json_object_object_add(root, "is_running", json_object_new_boolean(running));
|
||||
json_object_object_add(root, "output", json_object_new_string(content ? content : ""));
|
||||
if (!running) {
|
||||
json_object_object_add(root, "exit_status", json_object_new_int(exit_status));
|
||||
}
|
||||
|
||||
if (content && *content) {
|
||||
char *copy = strdup(content);
|
||||
char *saveptr;
|
||||
char *line = strtok_r(copy, "\n", &saveptr);
|
||||
while (line) {
|
||||
fprintf(stdout, "[%d]\t %s\n", pid, line);
|
||||
line = strtok_r(NULL, "\n", &saveptr);
|
||||
}
|
||||
fflush(stdout);
|
||||
free(copy);
|
||||
}
|
||||
|
||||
char *out_str = strdup(json_object_to_json_string_ext(root, JSON_C_TO_STRING_PRETTY));
|
||||
json_object_put(root);
|
||||
free(content);
|
||||
return out_str;
|
||||
}
|
||||
|
||||
static char *process_terminate_execute(tool_t *self, struct json_object *args) {
|
||||
(void)self;
|
||||
struct json_object *pid_obj;
|
||||
if (!json_object_object_get_ex(args, "pid", &pid_obj)) return strdup("Error: missing 'pid'");
|
||||
int pid = json_object_get_int(pid_obj);
|
||||
|
||||
kill(pid, SIGTERM);
|
||||
usleep(100000);
|
||||
if (kill(pid, 0) == 0) kill(pid, SIGKILL);
|
||||
|
||||
char log_path[256];
|
||||
snprintf(log_path, sizeof(log_path), "/tmp/r_process_%d.log", pid);
|
||||
unlink(log_path);
|
||||
|
||||
return strdup("Process terminated and logs cleaned up.");
|
||||
}
|
||||
|
||||
static struct json_object *process_monitor_get_description(void) {
|
||||
struct json_object *root = json_object_new_object();
|
||||
json_object_object_add(root, "type", json_object_new_string("function"));
|
||||
struct json_object *function = json_object_new_object();
|
||||
json_object_object_add(function, "name", json_object_new_string("process_monitor"));
|
||||
json_object_object_add(function, "description", json_object_new_string("Monitor and manage system processes."));
|
||||
json_object_object_add(function, "description", json_object_new_string("Monitor system processes. Use 'list' to see running processes (optionally with 'filter') and 'kill' to stop one."));
|
||||
struct json_object *parameters = json_object_new_object();
|
||||
json_object_object_add(parameters, "type", json_object_new_string("object"));
|
||||
struct json_object *properties = json_object_new_object();
|
||||
|
||||
struct json_object *action = json_object_new_object();
|
||||
json_object_object_add(action, "type", json_object_new_string("string"));
|
||||
json_object_object_add(action, "description", json_object_new_string("Action to perform: 'list' or 'kill'."));
|
||||
json_object_object_add(action, "description", json_object_new_string("Action: 'list' or 'kill'."));
|
||||
json_object_object_add(properties, "action", action);
|
||||
|
||||
struct json_object *filter = json_object_new_object();
|
||||
json_object_object_add(filter, "type", json_object_new_string("string"));
|
||||
json_object_object_add(filter, "description", json_object_new_string("Optional grep filter for 'list' action."));
|
||||
json_object_object_add(properties, "filter", filter);
|
||||
|
||||
struct json_object *pid = json_object_new_object();
|
||||
json_object_object_add(pid, "type", json_object_new_string("integer"));
|
||||
json_object_object_add(pid, "description", json_object_new_string("Process ID to kill (required for 'kill' action)."));
|
||||
json_object_object_add(pid, "description", json_object_new_string("PID for 'kill' action. Use 0 if not killing."));
|
||||
json_object_object_add(properties, "pid", pid);
|
||||
|
||||
struct json_object *as = json_object_new_object();
|
||||
json_object_object_add(as, "type", json_object_new_string("boolean"));
|
||||
json_object_object_add(as, "description", json_object_new_string("Not used for monitor but required for strict compliance."));
|
||||
json_object_object_add(properties, "async", as);
|
||||
|
||||
json_object_object_add(parameters, "properties", properties);
|
||||
struct json_object *required = json_object_new_array();
|
||||
json_object_array_add(required, json_object_new_string("action"));
|
||||
json_object_array_add(required, json_object_new_string("filter"));
|
||||
json_object_array_add(required, json_object_new_string("pid"));
|
||||
json_object_array_add(required, json_object_new_string("async"));
|
||||
json_object_object_add(parameters, "required", required);
|
||||
json_object_object_add(parameters, "additionalProperties", json_object_new_boolean(0));
|
||||
|
||||
json_object_object_add(function, "parameters", parameters);
|
||||
|
||||
r_config_handle cfg = r_config_get_instance();
|
||||
if (r_config_use_strict(cfg)) {
|
||||
json_object_object_add(function, "strict", json_object_new_boolean(1));
|
||||
}
|
||||
|
||||
if (r_config_use_strict(cfg)) json_object_object_add(function, "strict", json_object_new_boolean(1));
|
||||
json_object_object_add(root, "function", function);
|
||||
return root;
|
||||
}
|
||||
|
||||
static struct json_object *process_status_get_description(void) {
|
||||
struct json_object *root = json_object_new_object();
|
||||
json_object_object_add(root, "type", json_object_new_string("function"));
|
||||
struct json_object *f = json_object_new_object();
|
||||
json_object_object_add(f, "name", json_object_new_string("process_get_status"));
|
||||
json_object_object_add(f, "description", json_object_new_string("Get status, exit code, and logs of ANY background process (Python or Shell) by PID."));
|
||||
struct json_object *p = json_object_new_object();
|
||||
json_object_object_add(p, "type", json_object_new_string("object"));
|
||||
struct json_object *props = json_object_new_object();
|
||||
struct json_object *pid = json_object_new_object();
|
||||
json_object_object_add(pid, "type", json_object_new_string("integer"));
|
||||
json_object_object_add(props, "pid", pid);
|
||||
|
||||
struct json_object *as = json_object_new_object();
|
||||
json_object_object_add(as, "type", json_object_new_string("boolean"));
|
||||
json_object_object_add(as, "description", json_object_new_string("Required for strict mode."));
|
||||
json_object_object_add(props, "async", as);
|
||||
|
||||
json_object_object_add(p, "properties", props);
|
||||
struct json_object *req = json_object_new_array();
|
||||
json_object_array_add(req, json_object_new_string("pid"));
|
||||
json_object_array_add(req, json_object_new_string("async"));
|
||||
json_object_object_add(p, "required", req);
|
||||
json_object_object_add(p, "additionalProperties", json_object_new_boolean(0));
|
||||
json_object_object_add(f, "parameters", p);
|
||||
r_config_handle cfg = r_config_get_instance();
|
||||
if (r_config_use_strict(cfg)) json_object_object_add(f, "strict", json_object_new_boolean(1));
|
||||
json_object_object_add(root, "function", f);
|
||||
return root;
|
||||
}
|
||||
|
||||
static struct json_object *process_terminate_get_description(void) {
|
||||
struct json_object *root = json_object_new_object();
|
||||
json_object_object_add(root, "type", json_object_new_string("function"));
|
||||
struct json_object *f = json_object_new_object();
|
||||
json_object_object_add(f, "name", json_object_new_string("process_terminate"));
|
||||
json_object_object_add(f, "description", json_object_new_string("Terminate ANY background process (Python or Shell) and clean up."));
|
||||
struct json_object *p = json_object_new_object();
|
||||
json_object_object_add(p, "type", json_object_new_string("object"));
|
||||
struct json_object *props = json_object_new_object();
|
||||
struct json_object *pid = json_object_new_object();
|
||||
json_object_object_add(pid, "type", json_object_new_string("integer"));
|
||||
json_object_object_add(props, "pid", pid);
|
||||
|
||||
struct json_object *as = json_object_new_object();
|
||||
json_object_object_add(as, "type", json_object_new_string("boolean"));
|
||||
json_object_object_add(as, "description", json_object_new_string("Required for strict mode."));
|
||||
json_object_object_add(props, "async", as);
|
||||
|
||||
json_object_object_add(p, "properties", props);
|
||||
struct json_object *req = json_object_new_array();
|
||||
json_object_array_add(req, json_object_new_string("pid"));
|
||||
json_object_array_add(req, json_object_new_string("async"));
|
||||
json_object_object_add(p, "required", req);
|
||||
json_object_object_add(p, "additionalProperties", json_object_new_boolean(0));
|
||||
json_object_object_add(f, "parameters", p);
|
||||
r_config_handle cfg = r_config_get_instance();
|
||||
if (r_config_use_strict(cfg)) json_object_object_add(f, "strict", json_object_new_boolean(1));
|
||||
json_object_object_add(root, "function", f);
|
||||
return root;
|
||||
}
|
||||
+8
-152
@@ -18,12 +18,6 @@ static void terminal_print_action(const char *name, struct json_object *args);
|
||||
static struct json_object *terminal_interactive_get_description(void);
|
||||
static char *terminal_interactive_execute(tool_t *self, struct json_object *args);
|
||||
|
||||
static struct json_object *terminal_status_get_description(void);
|
||||
static char *terminal_status_execute(tool_t *self, struct json_object *args);
|
||||
|
||||
static struct json_object *terminal_terminate_get_description(void);
|
||||
static char *terminal_terminate_execute(tool_t *self, struct json_object *args);
|
||||
|
||||
static const tool_vtable_t terminal_vtable = {
|
||||
.get_description = terminal_get_description,
|
||||
.execute = terminal_execute,
|
||||
@@ -36,27 +30,11 @@ static const tool_vtable_t terminal_interactive_vtable = {
|
||||
.print_action = terminal_print_action
|
||||
};
|
||||
|
||||
static const tool_vtable_t terminal_status_vtable = {
|
||||
.get_description = terminal_status_get_description,
|
||||
.execute = terminal_status_execute,
|
||||
.print_action = NULL
|
||||
};
|
||||
|
||||
static const tool_vtable_t terminal_terminate_vtable = {
|
||||
.get_description = terminal_terminate_get_description,
|
||||
.execute = terminal_terminate_execute,
|
||||
.print_action = NULL
|
||||
};
|
||||
|
||||
static tool_t terminal_tool = { .vtable = &terminal_vtable, .name = "linux_terminal_execute" };
|
||||
static tool_t terminal_interactive_tool = { .vtable = &terminal_interactive_vtable, .name = "linux_terminal_execute_interactive" };
|
||||
static tool_t terminal_status_tool = { .vtable = &terminal_status_vtable, .name = "linux_terminal_get_status" };
|
||||
static tool_t terminal_terminate_tool = { .vtable = &terminal_terminate_vtable, .name = "linux_terminal_terminate" };
|
||||
|
||||
tool_t *tool_terminal_create(void) { return &terminal_tool; }
|
||||
tool_t *tool_terminal_interactive_create(void) { return &terminal_interactive_tool; }
|
||||
tool_t *tool_terminal_get_status_create(void) { return &terminal_status_tool; }
|
||||
tool_t *tool_terminal_terminate_create(void) { return &terminal_terminate_tool; }
|
||||
|
||||
static void terminal_print_action(const char *name, struct json_object *args) {
|
||||
if (!args) {
|
||||
@@ -122,87 +100,6 @@ static char *terminal_interactive_execute(tool_t *self, struct json_object *args
|
||||
return r_bash_execute(json_object_get_string(cmd_obj), true, timeout);
|
||||
}
|
||||
|
||||
static char *terminal_status_execute(tool_t *self, struct json_object *args) {
|
||||
(void)self;
|
||||
struct json_object *pid_obj;
|
||||
if (!json_object_object_get_ex(args, "pid", &pid_obj)) return strdup("Error: missing 'pid'");
|
||||
int pid = json_object_get_int(pid_obj);
|
||||
|
||||
int status;
|
||||
bool running = true;
|
||||
int exit_status = -1;
|
||||
|
||||
pid_t ret = waitpid(pid, &status, WNOHANG);
|
||||
if (ret == pid) {
|
||||
running = false;
|
||||
exit_status = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
|
||||
} else if (ret == -1) {
|
||||
// Not a child or already reaped
|
||||
running = (kill(pid, 0) == 0);
|
||||
}
|
||||
|
||||
char log_path[256];
|
||||
snprintf(log_path, sizeof(log_path), "/tmp/r_process_%d.log", pid);
|
||||
|
||||
char *content = NULL;
|
||||
FILE *f = fopen(log_path, "r");
|
||||
if (f) {
|
||||
fseek(f, 0, SEEK_END);
|
||||
long size = ftell(f);
|
||||
rewind(f);
|
||||
if (size >= 0) {
|
||||
content = malloc((size_t)size + 1);
|
||||
if (content) {
|
||||
size_t rs = fread(content, 1, (size_t)size, f);
|
||||
content[rs] = '\0';
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
struct json_object *root = json_object_new_object();
|
||||
json_object_object_add(root, "pid", json_object_new_int(pid));
|
||||
json_object_object_add(root, "is_running", json_object_new_boolean(running));
|
||||
json_object_object_add(root, "output", json_object_new_string(content ? content : ""));
|
||||
if (!running) {
|
||||
json_object_object_add(root, "exit_status", json_object_new_int(exit_status));
|
||||
}
|
||||
|
||||
if (content && *content) {
|
||||
char *copy = strdup(content);
|
||||
char *saveptr;
|
||||
char *line = strtok_r(copy, "\n", &saveptr);
|
||||
while (line) {
|
||||
fprintf(stdout, "[%d]\t %s\n", pid, line);
|
||||
line = strtok_r(NULL, "\n", &saveptr);
|
||||
}
|
||||
fflush(stdout);
|
||||
free(copy);
|
||||
}
|
||||
|
||||
char *out_str = strdup(json_object_to_json_string_ext(root, JSON_C_TO_STRING_PRETTY));
|
||||
json_object_put(root);
|
||||
free(content);
|
||||
return out_str;
|
||||
}
|
||||
|
||||
static char *terminal_terminate_execute(tool_t *self, struct json_object *args) {
|
||||
(void)self;
|
||||
struct json_object *pid_obj;
|
||||
if (!json_object_object_get_ex(args, "pid", &pid_obj)) return strdup("Error: missing 'pid'");
|
||||
int pid = json_object_get_int(pid_obj);
|
||||
|
||||
kill(pid, SIGTERM);
|
||||
usleep(100000);
|
||||
if (kill(pid, 0) == 0) kill(pid, SIGKILL);
|
||||
|
||||
char log_path[256];
|
||||
snprintf(log_path, sizeof(log_path), "/tmp/r_process_%d.log", pid);
|
||||
unlink(log_path);
|
||||
|
||||
return strdup("Process terminated and logs cleaned up.");
|
||||
}
|
||||
|
||||
static struct json_object *terminal_get_description(void) {
|
||||
struct json_object *root = json_object_new_object();
|
||||
json_object_object_add(root, "type", json_object_new_string("function"));
|
||||
@@ -255,10 +152,17 @@ static struct json_object *terminal_interactive_get_description(void) {
|
||||
struct json_object *to = json_object_new_object();
|
||||
json_object_object_add(to, "type", json_object_new_string("integer"));
|
||||
json_object_object_add(props, "timeout", to);
|
||||
|
||||
struct json_object *as = json_object_new_object();
|
||||
json_object_object_add(as, "type", json_object_new_string("boolean"));
|
||||
json_object_object_add(as, "description", json_object_new_string("Required for strict mode."));
|
||||
json_object_object_add(props, "async", as);
|
||||
|
||||
json_object_object_add(p, "properties", props);
|
||||
struct json_object *req = json_object_new_array();
|
||||
json_object_array_add(req, json_object_new_string("command"));
|
||||
json_object_array_add(req, json_object_new_string("timeout"));
|
||||
json_object_array_add(req, json_object_new_string("async"));
|
||||
json_object_object_add(p, "required", req);
|
||||
json_object_object_add(p, "additionalProperties", json_object_new_boolean(0));
|
||||
json_object_object_add(f, "parameters", p);
|
||||
@@ -266,52 +170,4 @@ static struct json_object *terminal_interactive_get_description(void) {
|
||||
if (r_config_use_strict(cfg)) json_object_object_add(f, "strict", json_object_new_boolean(1));
|
||||
json_object_object_add(root, "function", f);
|
||||
return root;
|
||||
}
|
||||
|
||||
static struct json_object *terminal_status_get_description(void) {
|
||||
struct json_object *root = json_object_new_object();
|
||||
json_object_object_add(root, "type", json_object_new_string("function"));
|
||||
struct json_object *f = json_object_new_object();
|
||||
json_object_object_add(f, "name", json_object_new_string("linux_terminal_get_status"));
|
||||
json_object_object_add(f, "description", json_object_new_string("Get status and logs of a background process by PID."));
|
||||
struct json_object *p = json_object_new_object();
|
||||
json_object_object_add(p, "type", json_object_new_string("object"));
|
||||
struct json_object *props = json_object_new_object();
|
||||
struct json_object *pid = json_object_new_object();
|
||||
json_object_object_add(pid, "type", json_object_new_string("integer"));
|
||||
json_object_object_add(props, "pid", pid);
|
||||
json_object_object_add(p, "properties", props);
|
||||
struct json_object *req = json_object_new_array();
|
||||
json_object_array_add(req, json_object_new_string("pid"));
|
||||
json_object_object_add(p, "required", req);
|
||||
json_object_object_add(p, "additionalProperties", json_object_new_boolean(0));
|
||||
json_object_object_add(f, "parameters", p);
|
||||
r_config_handle cfg = r_config_get_instance();
|
||||
if (r_config_use_strict(cfg)) json_object_object_add(f, "strict", json_object_new_boolean(1));
|
||||
json_object_object_add(root, "function", f);
|
||||
return root;
|
||||
}
|
||||
|
||||
static struct json_object *terminal_terminate_get_description(void) {
|
||||
struct json_object *root = json_object_new_object();
|
||||
json_object_object_add(root, "type", json_object_new_string("function"));
|
||||
struct json_object *f = json_object_new_object();
|
||||
json_object_object_add(f, "name", json_object_new_string("linux_terminal_terminate"));
|
||||
json_object_object_add(f, "description", json_object_new_string("Terminate a background process and clean up."));
|
||||
struct json_object *p = json_object_new_object();
|
||||
json_object_object_add(p, "type", json_object_new_string("object"));
|
||||
struct json_object *props = json_object_new_object();
|
||||
struct json_object *pid = json_object_new_object();
|
||||
json_object_object_add(pid, "type", json_object_new_string("integer"));
|
||||
json_object_object_add(props, "pid", pid);
|
||||
json_object_object_add(p, "properties", props);
|
||||
struct json_object *req = json_object_new_array();
|
||||
json_object_array_add(req, json_object_new_string("pid"));
|
||||
json_object_object_add(p, "required", req);
|
||||
json_object_object_add(p, "additionalProperties", json_object_new_boolean(0));
|
||||
json_object_object_add(f, "parameters", p);
|
||||
r_config_handle cfg = r_config_get_instance();
|
||||
if (r_config_use_strict(cfg)) json_object_object_add(f, "strict", json_object_new_boolean(1));
|
||||
json_object_object_add(root, "function", f);
|
||||
return root;
|
||||
}
|
||||
}
|
||||
+12
-10
@@ -5,8 +5,6 @@
|
||||
|
||||
extern tool_t *tool_terminal_create(void);
|
||||
extern tool_t *tool_terminal_interactive_create(void);
|
||||
extern tool_t *tool_terminal_get_status_create(void);
|
||||
extern tool_t *tool_terminal_terminate_create(void);
|
||||
extern tool_t *tool_read_file_create(void);
|
||||
extern tool_t *tool_write_file_create(void);
|
||||
extern tool_t *tool_directory_glob_create(void);
|
||||
@@ -20,14 +18,14 @@ extern tool_t *tool_db_get_create(void);
|
||||
extern tool_t *tool_db_set_create(void);
|
||||
extern tool_t *tool_db_query_create(void);
|
||||
extern tool_t *tool_python_execute_create(void);
|
||||
extern tool_t *tool_python_get_status_create(void);
|
||||
extern tool_t *tool_python_terminate_create(void);
|
||||
extern tool_t *tool_index_source_directory_create(void);
|
||||
extern tool_t *tool_code_grep_create(void);
|
||||
extern tool_t *tool_code_symbol_find_create(void);
|
||||
extern tool_t *tool_file_line_replace_create(void);
|
||||
extern tool_t *tool_file_apply_patch_create(void);
|
||||
extern tool_t *tool_process_monitor_create(void);
|
||||
extern tool_t *tool_process_get_status_create(void);
|
||||
extern tool_t *tool_process_terminate_create(void);
|
||||
extern tool_t *tool_network_check_create(void);
|
||||
extern tool_t *tool_dns_lookup_create(void);
|
||||
extern tool_t *tool_network_port_scan_create(void);
|
||||
@@ -46,8 +44,6 @@ tool_registry_t *tools_get_registry(void) {
|
||||
|
||||
tool_registry_register(global_registry, tool_terminal_create());
|
||||
tool_registry_register(global_registry, tool_terminal_interactive_create());
|
||||
tool_registry_register(global_registry, tool_terminal_get_status_create());
|
||||
tool_registry_register(global_registry, tool_terminal_terminate_create());
|
||||
tool_registry_register(global_registry, tool_read_file_create());
|
||||
tool_registry_register(global_registry, tool_write_file_create());
|
||||
tool_registry_register(global_registry, tool_directory_glob_create());
|
||||
@@ -61,16 +57,16 @@ tool_registry_t *tools_get_registry(void) {
|
||||
tool_registry_register(global_registry, tool_db_set_create());
|
||||
tool_registry_register(global_registry, tool_db_query_create());
|
||||
tool_registry_register(global_registry, tool_python_execute_create());
|
||||
tool_registry_register(global_registry, tool_python_get_status_create());
|
||||
tool_registry_register(global_registry, tool_python_terminate_create());
|
||||
tool_registry_register(global_registry, tool_index_source_directory_create());
|
||||
|
||||
// New tools
|
||||
// New & Refined tools
|
||||
tool_registry_register(global_registry, tool_code_grep_create());
|
||||
tool_registry_register(global_registry, tool_code_symbol_find_create());
|
||||
tool_registry_register(global_registry, tool_file_line_replace_create());
|
||||
tool_registry_register(global_registry, tool_file_apply_patch_create());
|
||||
tool_registry_register(global_registry, tool_process_monitor_create());
|
||||
tool_registry_register(global_registry, tool_process_get_status_create());
|
||||
tool_registry_register(global_registry, tool_process_terminate_create());
|
||||
tool_registry_register(global_registry, tool_network_check_create());
|
||||
tool_registry_register(global_registry, tool_dns_lookup_create());
|
||||
tool_registry_register(global_registry, tool_network_port_scan_create());
|
||||
@@ -110,6 +106,8 @@ tool_registry_t *tool_registry_get_specialized(tool_registry_type_t type) {
|
||||
tool_registry_register(reg, tool_code_symbol_find_create());
|
||||
tool_registry_register(reg, tool_file_line_replace_create());
|
||||
tool_registry_register(reg, tool_file_apply_patch_create());
|
||||
tool_registry_register(reg, tool_process_get_status_create());
|
||||
tool_registry_register(reg, tool_process_terminate_create());
|
||||
tool_registry_register(reg, tool_spawn_agent_create());
|
||||
} else if (type == TOOL_TYPE_SECURITY) {
|
||||
tool_registry_register(reg, tool_terminal_create());
|
||||
@@ -121,11 +119,15 @@ tool_registry_t *tool_registry_get_specialized(tool_registry_type_t type) {
|
||||
tool_registry_register(reg, tool_web_search_create());
|
||||
tool_registry_register(reg, tool_http_fetch_create());
|
||||
tool_registry_register(reg, tool_process_monitor_create());
|
||||
tool_registry_register(reg, tool_process_get_status_create());
|
||||
tool_registry_register(reg, tool_process_terminate_create());
|
||||
tool_registry_register(reg, tool_spawn_agent_create());
|
||||
} else {
|
||||
// Fallback or TOOL_TYPE_ALL
|
||||
tool_registry_register(reg, tool_terminal_create());
|
||||
tool_registry_register(reg, tool_read_file_create());
|
||||
tool_registry_register(reg, tool_process_get_status_create());
|
||||
tool_registry_register(reg, tool_process_terminate_create());
|
||||
tool_registry_register(reg, tool_spawn_agent_create());
|
||||
}
|
||||
|
||||
@@ -137,4 +139,4 @@ void tools_registry_shutdown(void) {
|
||||
tool_registry_destroy(global_registry);
|
||||
global_registry = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user