Ship Assistent 0.8.1: split modules and shared+personal vector memory.
Personal RAG never leaks into the shared store; retrieve merges shared plus the persona chain, with personal overwrite on kind+key. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
using System;
|
||||
using System.Text.RegularExpressions;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace Mrleo1nid.SwarmAssistent;
|
||||
|
||||
/// <summary>Parsing and normalization of the JSON patch the model emits inside fenced code blocks.</summary>
|
||||
public partial class SwarmAssistentExtension
|
||||
{
|
||||
static readonly Regex JsonFenceRe = new(@"```(?:json)?\s*([\s\S]*?)```", RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||||
|
||||
static readonly string[] PatchKeys =
|
||||
[
|
||||
"prompt", "loras", "width", "height", "steps", "cfg", "seed", "sigma_shift", "sampler",
|
||||
"actions", "search_query", "civitai_query",
|
||||
"use_init_image", "clear_init_image", "init_creativity", "denoise",
|
||||
"use_mask_image", "clear_mask_image", "mask_blur", "mask_grow",
|
||||
"look_at", "vision_from", "vision_slots", "slot_to_init", "slot_to_mask",
|
||||
"snapshot_generate", "select_slot", "aspect", "images", "batch", "vary", "lock_seed",
|
||||
"creativity", "intensity", "complexity", "movement",
|
||||
"clear_prompt_images", "slot_to_prompt_image", "pack", "memories", "memory",
|
||||
];
|
||||
|
||||
static bool HasValue(JObject obj, string key)
|
||||
{
|
||||
JToken token = obj?[key];
|
||||
return token is not null && token.Type != JTokenType.Null;
|
||||
}
|
||||
|
||||
/// <summary>Maps legacy/alias patch fields onto their canonical names. Aliases are kept so older consumers still work.</summary>
|
||||
public static JObject NormalizePatch(JObject patch)
|
||||
{
|
||||
if (patch is null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (!HasValue(patch, "search_query") && HasValue(patch, "civitai_query"))
|
||||
{
|
||||
patch["search_query"] = patch["civitai_query"];
|
||||
}
|
||||
if (!HasValue(patch, "init_creativity") && HasValue(patch, "denoise"))
|
||||
{
|
||||
patch["init_creativity"] = patch["denoise"];
|
||||
}
|
||||
if (!HasValue(patch, "look_at"))
|
||||
{
|
||||
if (HasValue(patch, "vision_from"))
|
||||
{
|
||||
patch["look_at"] = patch["vision_from"];
|
||||
}
|
||||
else if (HasValue(patch, "vision_slots"))
|
||||
{
|
||||
patch["look_at"] = patch["vision_slots"];
|
||||
}
|
||||
}
|
||||
return patch;
|
||||
}
|
||||
|
||||
static JObject TryParsePatch(string reply)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(reply))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
foreach (Match match in JsonFenceRe.Matches(reply))
|
||||
{
|
||||
string raw = match.Groups[1].Value.Trim();
|
||||
try
|
||||
{
|
||||
JObject obj = JObject.Parse(raw);
|
||||
if (obj is not null && Array.Exists(PatchKeys, k => obj[k] is not null))
|
||||
{
|
||||
return NormalizePatch(obj);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// not json
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static string ExtractSearchQuery(JObject patch)
|
||||
{
|
||||
if (patch is null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
string q = (patch["search_query"] ?? patch["civitai_query"])?.ToString()?.Trim();
|
||||
return string.IsNullOrWhiteSpace(q) ? null : q;
|
||||
}
|
||||
|
||||
static bool WantsCivitaiSearch(JObject patch)
|
||||
{
|
||||
return !string.IsNullOrWhiteSpace(ExtractSearchQuery(patch));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user