fix: custom command execution via systemd-run für prozessunabhängigkeit

This commit is contained in:
Meleki committed 2026-02-27 13:34:14 +01:00
1 parent 2b8749ee3a
commit 73c6d38254
11 files changed
+242 -12

No files matched your search

+1 -1
View File
@@ -84,7 +84,7 @@ public static class ChatEndpoint
promptParts.Add($"## Instructions\n{agent.Instructions}");
if (!string.IsNullOrWhiteSpace(session.Workspace))
promptParts.Add($"## Workspace\n{session.Workspace}");
promptParts.Add("## Tools\nDu hast Tools zur Verfügung (read_file, write_file, edit_file, list_files, delete_file, execute). Benutze sie um Dateien zu lesen, schreiben und bearbeiten. Beschreibe NICHT was du tun würdest - tu es einfach über die Tools.");
if (!string.IsNullOrWhiteSpace(session.Context))
promptParts.Add($"## Kontext\n{session.Context}");
+68 -2
View File
@@ -1,4 +1,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text.Json;
using System.Threading.Tasks;
@@ -19,6 +21,7 @@ public static class SessionEndpoint
app.MapPut("/api/sessions/{sessionId}", HandleUpdate);
app.MapDelete("/api/sessions/{sessionId}", HandleDelete);
app.MapGet("/api/sessions/{sessionId}/system-prompt", HandleSystemPrompt);
app.MapPost("/api/sessions/{sessionId}/exec", HandleExec);
}
private static async Task HandleList(HttpContext ctx, DatabaseService db)
@@ -54,8 +57,9 @@ public static class SessionEndpoint
var agentId = body.TryGetProperty("agentId", out var a) ? a.GetString() : null;
var workspace = body.TryGetProperty("workspace", out var w) ? w.GetString() : null;
var context = body.TryGetProperty("context", out var ctxEl) ? ctxEl.GetString() : null;
var customCommands = body.TryGetProperty("customCommands", out var cc) && cc.ValueKind != JsonValueKind.Null ? cc.GetRawText() : null;
var session = await db.CreateSession(name, description, image, agentId, workspace, context);
var session = await db.CreateSession(name, description, image, agentId, workspace, context, customCommands);
await ctx.Response.WriteAsJsonAsync(session);
}
@@ -122,7 +126,7 @@ public static class SessionEndpoint
if (!string.IsNullOrWhiteSpace(agent.Instructions))
promptParts.Add($"## Instructions\n{agent.Instructions}");
if (!string.IsNullOrWhiteSpace(session.Workspace))
promptParts.Add($"## Workspace\n{session.Workspace}");
promptParts.Add("## Tools\nDu hast Tools zur Verfügung (read_file, write_file, edit_file, list_files, delete_file, execute). Benutze sie um Dateien zu lesen, schreiben und bearbeiten. Beschreibe NICHT was du tun würdest - tu es einfach über die Tools.");
if (!string.IsNullOrWhiteSpace(session.Context))
promptParts.Add($"## Kontext\n{session.Context}");
@@ -131,4 +135,66 @@ public static class SessionEndpoint
ctx.Response.ContentType = "text/plain; charset=utf-8";
await ctx.Response.WriteAsync(systemPrompt);
}
private static async Task HandleExec(HttpContext ctx, DatabaseService db)
{
var sessionId = ctx.Request.RouteValues["sessionId"]?.ToString();
if (string.IsNullOrEmpty(sessionId))
{
ctx.Response.StatusCode = 400;
return;
}
var session = await db.GetSession(sessionId);
if (session == null)
{
ctx.Response.StatusCode = 404;
return;
}
var body = await JsonSerializer.DeserializeAsync<JsonElement>(ctx.Request.Body);
var command = body.TryGetProperty("command", out var c) ? c.GetString() : null;
if (string.IsNullOrWhiteSpace(command))
{
ctx.Response.StatusCode = 400;
await ctx.Response.WriteAsJsonAsync(new { error = "Kein Befehl angegeben" });
return;
}
var workingDir = !string.IsNullOrWhiteSpace(session.Workspace) ? session.Workspace : "/tmp";
try
{
var scriptPath = $"/tmp/gott-exec-{Guid.NewGuid():N}.sh";
await System.IO.File.WriteAllTextAsync(scriptPath, $"#!/bin/bash\ncd {workingDir}\n{command}\nrm -f {scriptPath}\n");
var psi = new ProcessStartInfo
{
FileName = "systemd-run",
Arguments = $"--scope --quiet bash {scriptPath}",
WorkingDirectory = workingDir,
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = true
};
var process = Process.Start(psi);
if (process != null)
{
process.WaitForExit(5000);
}
ctx.Response.StatusCode = 202;
await ctx.Response.WriteAsJsonAsync(new { status = "started", command = command });
}
catch (Exception ex)
{
ctx.Response.StatusCode = 500;
await ctx.Response.WriteAsJsonAsync(new { error = ex.Message });
}
}
}