Ship Assistent 0.11.3: variants grid, EN Krea prep, and stream fence fix.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+77
-10
@@ -21,6 +21,7 @@ public partial class SwarmAssistentExtension
|
||||
"clear_prompt_images", "slot_to_prompt_image", "pack", "memories", "memory",
|
||||
"memory_query", "memory_kind", "tag_query", "user_prefs",
|
||||
"inventory_query", "skills", "persona_shelves", "controls",
|
||||
"variants",
|
||||
];
|
||||
|
||||
static bool HasValue(JObject obj, string key)
|
||||
@@ -107,8 +108,10 @@ public partial class SwarmAssistentExtension
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If the reply already contains a closed fenced patch/card, cut everything after it.
|
||||
/// Models often keep writing («Готово!», second aspect, …) and the stream never feels done.
|
||||
/// If the reply already contains a closed fenced patch/card that is "done enough" to act on,
|
||||
/// cut everything after it. Do NOT stop on weak fences (pack/creativity/notes-only) — models
|
||||
/// often emit a tiny JSON first then the real prompt fence; aborting early cuts the prompt
|
||||
/// and blocks skill_load / generate.
|
||||
/// </summary>
|
||||
static bool TryTruncateAtCompleteFence(string reply, out string truncated)
|
||||
{
|
||||
@@ -129,18 +132,11 @@ public partial class SwarmAssistentExtension
|
||||
try
|
||||
{
|
||||
JObject obj = JObject.Parse(raw);
|
||||
if (obj is null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
bool usable = LooksLikeCardObject(obj)
|
||||
|| Array.Exists(PatchKeys, k => obj[k] is not null);
|
||||
if (!usable)
|
||||
if (obj is null || !FenceIsTerminalPatch(obj))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
truncated = reply.Substring(0, match.Index + match.Length).TrimEnd();
|
||||
// Only treat as complete if the fence actually closed (regex requires ```).
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
@@ -151,6 +147,77 @@ public partial class SwarmAssistentExtension
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// True when a closed fence is worth aborting the Ollama stream (real deliverable or tool hop).
|
||||
/// </summary>
|
||||
static bool FenceIsTerminalPatch(JObject obj)
|
||||
{
|
||||
if (obj is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (LooksLikeCardObject(obj))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (obj["variants"] is JArray variants && variants.Count > 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (HasValue(obj, "look_at") || HasValue(obj, "vision_from") || HasValue(obj, "vision_slots"))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (HasValue(obj, "search_query") || HasValue(obj, "civitai_query"))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (HasValue(obj, "memory_query") || HasValue(obj, "tag_query") || HasValue(obj, "inventory_query"))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (obj["actions"] is JArray acts)
|
||||
{
|
||||
foreach (JToken a in acts)
|
||||
{
|
||||
string s = a?.ToString() ?? "";
|
||||
if (string.IsNullOrWhiteSpace(s))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (s.Equals("skill_load", StringComparison.OrdinalIgnoreCase)
|
||||
|| s.Equals("persona_read", StringComparison.OrdinalIgnoreCase)
|
||||
|| s.Equals("memory_get", StringComparison.OrdinalIgnoreCase)
|
||||
|| s.Equals("memory_search", StringComparison.OrdinalIgnoreCase)
|
||||
|| s.Equals("lookup_tags", StringComparison.OrdinalIgnoreCase)
|
||||
|| s.Equals("list_inventory", StringComparison.OrdinalIgnoreCase)
|
||||
|| s.Equals("search_civitai", StringComparison.OrdinalIgnoreCase)
|
||||
|| s.Equals("interrupt", StringComparison.OrdinalIgnoreCase)
|
||||
|| s.Equals("generate", StringComparison.OrdinalIgnoreCase)
|
||||
|| s.Equals("memory_upsert", StringComparison.OrdinalIgnoreCase)
|
||||
|| s.Equals("user_pref_upsert", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
string prompt = obj["prompt"]?.ToString()?.Trim() ?? "";
|
||||
if (prompt.Length >= 48)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
// Real param change without prose notes
|
||||
if (HasValue(obj, "loras") || HasValue(obj, "aspect") || HasValue(obj, "steps")
|
||||
|| HasValue(obj, "width") || HasValue(obj, "height") || HasValue(obj, "cfg")
|
||||
|| HasValue(obj, "seed") || HasValue(obj, "controls")
|
||||
|| HasValue(obj, "memories") || HasValue(obj, "user_prefs"))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
// Weak: pack / creativity / intensity / empty actions / notes-only → keep streaming
|
||||
return false;
|
||||
}
|
||||
|
||||
static string ExtractSearchQuery(JObject patch)
|
||||
{
|
||||
if (patch is null)
|
||||
|
||||
Reference in New Issue
Block a user