diff --git a/Endpoints/SessionEndpoint.cs b/Endpoints/SessionEndpoint.cs index 7fe7257..8f6ae58 100644 --- a/Endpoints/SessionEndpoint.cs +++ b/Endpoints/SessionEndpoint.cs @@ -16,6 +16,7 @@ public static class SessionEndpoint app.MapGet("/api/sessions/{sessionId}", HandleGet); app.MapPost("/api/sessions", HandleCreate); app.MapPut("/api/sessions/{sessionId}", HandleUpdate); + app.MapDelete("/api/sessions/{sessionId}", HandleDelete); } private static async Task HandleList(HttpContext ctx, DatabaseService db) @@ -43,7 +44,14 @@ public static class SessionEndpoint private static async Task HandleCreate(HttpContext ctx, DatabaseService db) { - var session = await db.CreateSession("Neue Session"); + var body = await JsonSerializer.DeserializeAsync(ctx.Request.Body); + + var name = body.TryGetProperty("name", out var n) ? n.GetString() : "Neue Session"; + var description = body.TryGetProperty("description", out var d) ? d.GetString() : null; + var image = body.TryGetProperty("image", out var img) ? img.GetString() : null; + var agentId = body.TryGetProperty("agentId", out var a) ? a.GetString() : null; + + var session = await db.CreateSession(name, description, image, agentId); await ctx.Response.WriteAsJsonAsync(session); } @@ -57,16 +65,18 @@ public static class SessionEndpoint } var body = await JsonSerializer.DeserializeAsync(ctx.Request.Body); - if (body.TryGetProperty("name", out var nameEl)) - { - await db.UpdateSessionName(sessionId, nameEl.GetString()); - } - if (body.TryGetProperty("agentId", out var agentEl)) - { - await db.UpdateSessionAgent(sessionId, agentEl.GetString()); - } + await db.UpdateSession(sessionId, body); var session = await db.GetSession(sessionId); await ctx.Response.WriteAsJsonAsync(session); } + + private static async Task HandleDelete(HttpContext ctx, DatabaseService db) + { + var sessionId = ctx.Request.RouteValues["sessionId"]?.ToString(); + if (string.IsNullOrEmpty(sessionId)) { ctx.Response.StatusCode = 400; return; } + + await db.DeleteSession(sessionId); + ctx.Response.StatusCode = 204; + } } diff --git a/Models/SessionRecord.cs b/Models/SessionRecord.cs index 7e1dbdc..4a7a62e 100644 --- a/Models/SessionRecord.cs +++ b/Models/SessionRecord.cs @@ -5,7 +5,10 @@ public class SessionRecord public long Id { get; set; } public string SessionId { get; set; } public string Name { get; set; } + public string Description { get; set; } + public string Image { get; set; } public string AgentId { get; set; } + public bool IsDeleted { get; set; } public string CreatedAt { get; set; } public string UpdatedAt { get; set; } } diff --git a/Services/DatabaseService.cs b/Services/DatabaseService.cs index cd8042c..9d8f64d 100644 --- a/Services/DatabaseService.cs +++ b/Services/DatabaseService.cs @@ -99,6 +99,9 @@ public class DatabaseService // Migrations TryAddColumn(conn, "sessions", "agent_id", "TEXT"); + TryAddColumn(conn, "sessions", "description", "TEXT"); + TryAddColumn(conn, "sessions", "image", "TEXT"); + TryAddColumn(conn, "sessions", "is_deleted", "INTEGER NOT NULL DEFAULT 0"); TryAddColumn(conn, "chains", "agent_id", "TEXT"); } @@ -159,7 +162,7 @@ public class DatabaseService // ── Sessions ── - public async Task CreateSession(string name = null) + public async Task CreateSession(string name = null, string description = null, string image = null, string agentId = null) { using var conn = CreateConnection(); var now = DateTime.UtcNow.ToString("o"); @@ -167,12 +170,15 @@ public class DatabaseService { SessionId = Guid.NewGuid().ToString("N"), Name = name, + Description = description, + Image = image, + AgentId = agentId, CreatedAt = now, UpdatedAt = now }; await conn.ExecuteAsync(@" - INSERT INTO sessions (session_id, name, created_at, updated_at) - VALUES (@SessionId, @Name, @CreatedAt, @UpdatedAt) + INSERT INTO sessions (session_id, name, description, image, agent_id, created_at, updated_at) + VALUES (@SessionId, @Name, @Description, @Image, @AgentId, @CreatedAt, @UpdatedAt) ", session); return session; } @@ -181,14 +187,14 @@ public class DatabaseService { using var conn = CreateConnection(); return await conn.QueryAsync( - "SELECT * FROM sessions ORDER BY updated_at DESC"); + "SELECT * FROM sessions WHERE is_deleted = 0 ORDER BY updated_at DESC"); } public async Task GetSession(string sessionId) { using var conn = CreateConnection(); return await conn.QuerySingleOrDefaultAsync( - "SELECT * FROM sessions WHERE session_id = @sessionId", new { sessionId }); + "SELECT * FROM sessions WHERE session_id = @sessionId AND is_deleted = 0", new { sessionId }); } public async Task UpdateSessionTimestamp(string sessionId) @@ -199,20 +205,28 @@ public class DatabaseService new { sessionId, now = DateTime.UtcNow.ToString("o") }); } - public async Task UpdateSessionName(string sessionId, string name) + public async Task UpdateSession(string sessionId, System.Text.Json.JsonElement body) { using var conn = CreateConnection(); - await conn.ExecuteAsync( - "UPDATE sessions SET name = @name, updated_at = @now WHERE session_id = @sessionId", - new { sessionId, name, now = DateTime.UtcNow.ToString("o") }); + var sets = new List { "updated_at = @now" }; + var p = new Dapper.DynamicParameters(); + p.Add("sessionId", sessionId); + p.Add("now", DateTime.UtcNow.ToString("o")); + + if (body.TryGetProperty("name", out var n)) { sets.Add("name = @name"); p.Add("name", n.GetString()); } + if (body.TryGetProperty("description", out var d)) { sets.Add("description = @desc"); p.Add("desc", d.GetString()); } + if (body.TryGetProperty("image", out var img)) { sets.Add("image = @image"); p.Add("image", img.GetString()); } + if (body.TryGetProperty("agentId", out var a)) { sets.Add("agent_id = @agentId2"); p.Add("agentId2", a.GetString()); } + + await conn.ExecuteAsync($"UPDATE sessions SET {string.Join(", ", sets)} WHERE session_id = @sessionId", p); } - public async Task UpdateSessionAgent(string sessionId, string agentId) + public async Task DeleteSession(string sessionId) { using var conn = CreateConnection(); await conn.ExecuteAsync( - "UPDATE sessions SET agent_id = @agentId, updated_at = @now WHERE session_id = @sessionId", - new { sessionId, agentId, now = DateTime.UtcNow.ToString("o") }); + "UPDATE sessions SET is_deleted = 1, updated_at = @now WHERE session_id = @sessionId", + new { sessionId, now = DateTime.UtcNow.ToString("o") }); } // ── Archives ── diff --git a/wwwroot/css/base.css b/wwwroot/css/base.css index 3610ea3..2d409d8 100644 --- a/wwwroot/css/base.css +++ b/wwwroot/css/base.css @@ -107,8 +107,7 @@ header { } .msg { - max-width: 85%; - padding: var(--s4); + padding: var(--s3) var(--s4); white-space: pre-wrap; word-break: break-word; } @@ -129,6 +128,7 @@ header { align-self: center; border: var(--border-width) solid var(--f2-border); text-align: center; + padding: var(--s2); } /* ── Cursor ── */ diff --git a/wwwroot/css/main.css b/wwwroot/css/main.css index c77bb8e..a022f15 100644 --- a/wwwroot/css/main.css +++ b/wwwroot/css/main.css @@ -69,19 +69,63 @@ body { .card { background: var(--f3-bg); border: var(--border-width) solid var(--f3-border); - padding: var(--s4); display: flex; flex-direction: column; - gap: var(--s2); + overflow: hidden; } .card.clickable { cursor: pointer; } .card.clickable:hover { border-color: var(--primary); } -.card-icon { font-size: 2em; } +.card-image { + aspect-ratio: 1; + background: var(--f2-bg); + overflow: hidden; +} + +.card-image img { + width: 100%; + height: 100%; + object-fit: cover; +} + +.card-body { + padding: var(--s3); + display: flex; + flex-direction: column; + gap: var(--s1); +} + +.card-title-row { + display: flex; + align-items: center; + gap: var(--s2); +} + +.card-title { + font-weight: bold; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.card-desc { + display: -webkit-box; + overflow: hidden; +} + +.badge { + padding: var(--s1) var(--s2); + background: var(--f1-bg); + border: var(--border-width) solid var(--f2-border); + white-space: nowrap; + flex-shrink: 0; +} .card.placeholder { border-style: dashed; + align-items: center; + justify-content: center; } /* ── Session Page ── */ @@ -189,23 +233,3 @@ body { background: #ff6b6b; color: var(--f1-bg); } - -/* ── Agent Card Avatar ── */ - -.agent-card-avatar { - width: 40px; - height: 40px; - background: var(--f2-bg); - border: var(--border-width) solid var(--f2-border); - display: flex; - align-items: center; - justify-content: center; - font-size: 1.2em; - overflow: hidden; -} - -.agent-card-avatar img { - width: 100%; - height: 100%; - object-fit: cover; -} diff --git a/wwwroot/index.html b/wwwroot/index.html index d2b6a46..d7d8031 100644 --- a/wwwroot/index.html +++ b/wwwroot/index.html @@ -27,7 +27,6 @@

Sessions

-
@@ -48,11 +47,39 @@ + +