You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@skywalking.apache.org by wu...@apache.org on 2026/09/17 01:44:49 UTC

(skywalking-ai-sessionizer) 01/01: Draw a compaction as a compaction in asz view

This is an automated email from the ASF dual-hosted git repository.

wu-sheng pushed a commit to branch horizon-compaction-wording
in repository https://gitbox.apache.org/repos/asf/skywalking-ai-sessionizer.git

commit fea9a9d2d42f50ed4a041614251923fbd66facd8
Author: Wu Sheng <wu...@foxmail.com>
AuthorDate: Thu Sep 17 09:44:38 2026 +0800

    Draw a compaction as a compaction in asz view
    
    The embedded renderer moves to Horizon 53c1f63b (#166). The one before it
    compared a message of one text block as two different messages depending on
    whether it was the newest, since the runtime sends it as a list while it is and
    as a plain string after. So it reported an ordinary growth step as a rewritten
    history: on one real 94-call conversation, 60 of 62 of them.
    
    The prompt tab now reads both spellings as one message, and says which of two
    things happened when the history does change: the context was replaced by a
    summary, with how many messages became how many, or, when the history changed
    without getting shorter, a warning.
    
    asz view and the SkyWalking UI draw a conversation from the same renderer, so
    this keeps the page beside the storage root from warning where the UI does not.
---
 internal/view/conversation-view/HORIZON_COMMIT     |  2 +-
 .../view/conversation-view/conversation-view.js    | 24 +++++++++++++++++-----
 2 files changed, 20 insertions(+), 6 deletions(-)

diff --git a/internal/view/conversation-view/HORIZON_COMMIT b/internal/view/conversation-view/HORIZON_COMMIT
index 0fdf6e2..59fd670 100644
--- a/internal/view/conversation-view/HORIZON_COMMIT
+++ b/internal/view/conversation-view/HORIZON_COMMIT
@@ -1,3 +1,3 @@
-commit 0ce1f8d6a8484b127abf83897b0aa4f5f567f363
+commit 53c1f63b635bc8efbaec0e4bc28ec9539e526328
 package @skywalking-horizon-ui/conversation-view 1.1.0-dev
 source https://github.com/apache/skywalking-horizon-ui.git
diff --git a/internal/view/conversation-view/conversation-view.js b/internal/view/conversation-view/conversation-view.js
index 05efc8e..c91d01a 100644
--- a/internal/view/conversation-view/conversation-view.js
+++ b/internal/view/conversation-view/conversation-view.js
@@ -1187,7 +1187,8 @@ const ENGLISH = {
   promptSettings: "Settings",
   promptBlocks: "{count} block(s), {bytes} bytes",
   promptShared: "The {count} message(s) before are as the call before sent them, {bytes} bytes.",
-  promptRewritten: "The history was rewritten, which is what a compaction does.",
+  promptRewritten: "The history before this point was rewritten, and not by a compaction.",
+  promptCompacted: "The context was replaced by a summary here, so the list starts again: {before} message(s) became {after}.",
   promptAlsoChanged: "Also changed: {what}.",
   promptAdded: "Added by this call ({count})",
   promptNothingAdded: "This request adds no message.",
@@ -1835,6 +1836,7 @@ function deltaOf(previous, current) {
   const least = Math.min(previous.messages.length, current.messages.length);
   while (shared < least && same(previous.messages[shared].raw, current.messages[shared].raw, MARKED_IN_MESSAGE)) shared++;
   if (shared < least) rewritten = true;
+  const replaced = rewritten && current.messages.length < previous.messages.length;
   const added = current.messages.slice(shared);
   let sharedBytes = 0;
   for (let i = 0; i < shared; i++) sharedBytes += size(current.messages[i].raw);
@@ -1843,6 +1845,7 @@ function deltaOf(previous, current) {
     sharedMessages: shared,
     sharedBytes,
     rewritten,
+    replaced,
     systemChanged: !same(previous.raw["system"], current.raw["system"], MARKED_IN_LIST),
     toolsChanged: !same(previous.raw["tools"], current.raw["tools"], MARKED_IN_LIST),
     settingsChanged: !same(settings(previous), settings(current), NOT_MARKED)
@@ -1866,10 +1869,18 @@ function canonical(value, markedTo, depth = 0) {
   const parts = [];
   for (const k of Object.keys(obj).sort()) {
     if (depth <= markedTo && k === "cache_control") continue;
-    parts.push(`${JSON.stringify(k)}:${canonical(obj[k], markedTo, depth + 1)}`);
+    const v = k === "content" && depth < markedTo ? plainContent(obj[k]) : obj[k];
+    parts.push(`${JSON.stringify(k)}:${canonical(v, markedTo, depth + 1)}`);
   }
   return `{${parts.join(",")}}`;
 }
+function plainContent(content) {
+  if (typeof content === "string") return [{ type: "text", text: content }];
+  if (!Array.isArray(content) || content.length !== 1) return content;
+  const only = content[0];
+  if (!only || typeof only !== "object" || only["type"] !== "text" || typeof only["text"] !== "string") return content;
+  return [{ type: "text", text: only["text"] }];
+}
 const LINE_DIFF_CAP = 400;
 function lineDiff(before, after) {
   const a = before.split("\n");
@@ -2277,7 +2288,7 @@ function drawRequest(ctx, e, read2, sides, store) {
     </div>`;
   if (!state.promptWhole) {
     if (!previous) return `${modes}<div class="acv-empty">${esc(s.promptNoPrevious)}</div>`;
-    return `${modes}${drawDelta(ctx, e, deltaOf(previous, read2), read2)}`;
+    return `${modes}${drawDelta(ctx, e, deltaOf(previous, read2), read2, previous.messages.length)}`;
   }
   const system = read2.system.length ? section(ctx, e, "system", s.promptSystem, blockSummary(ctx, read2.system), read2.system.map((b, i) => block(ctx, b, `${e.id}|req|sys|${i}`)).join("")) : "";
   const tools = read2.tools.length ? section(
@@ -2324,7 +2335,7 @@ function previousRequest(ctx, e, sides, store) {
   }
   return null;
 }
-function drawDelta(ctx, e, delta, read2) {
+function drawDelta(ctx, e, delta, read2, previousCount) {
   const { s, f } = ctx;
   const changed = [
     delta.systemChanged ? s.promptSystem : "",
@@ -2333,7 +2344,10 @@ function drawDelta(ctx, e, delta, read2) {
   ].filter(Boolean);
   const notes = [
     `<div class="acv-faint">${esc(fill(s.promptShared, { count: String(delta.sharedMessages), bytes: f.number(delta.sharedBytes) }))}</div>`,
-    delta.rewritten ? `<div class="acv-warning">${esc(s.promptRewritten)}</div>` : "",
+    // A compaction is not a fault: it is the runtime replacing the context with a summary, which the
+    // conversation records as its own step. Saying which of the two happened is the whole value of
+    // the note -- a warning on every ordinary growth would say nothing.
+    delta.replaced ? `<div class="acv-faint">${esc(fill(s.promptCompacted, { before: String(previousCount), after: String(read2.messages.length) }))}</div>` : delta.rewritten ? `<div class="acv-warning">${esc(s.promptRewritten)}</div>` : "",
     changed.length ? `<div class="acv-faint">${esc(fill(s.promptAlsoChanged, { what: changed.join(", ") }))}</div>` : ""
   ].join("");
   const added = delta.added.length ? delta.added.map((m, i) => message(ctx, m, delta.sharedMessages + i + 1, read2.messages.length, `${e.id}|req|msg|${delta.sharedMessages + i}`)).join("") : `<div class="acv-empty">${esc(s.promptNothingAdded)}</div>`;