fixup! fixup! fixup! fixup! chore: update marketplace for v0.11.37

march-improvements
This commit is contained in:
2026-03-07 00:08:18 +00:00
parent 5a81f37779
commit a1d4459329
9 changed files with 202 additions and 9 deletions
+3 -2
View File
@@ -10,6 +10,7 @@ import (
"time"
"github.com/lukaszraczylo/claude-mnemonic/pkg/hooks"
"github.com/lukaszraczylo/claude-mnemonic/pkg/sanitize"
)
// Input is the hook input from Claude Code.
@@ -148,14 +149,14 @@ func handleUserPrompt(ctx *hooks.HookContext, input *Input) (string, error) {
obsText += "Key facts:\n"
for _, fact := range facts {
if factStr, ok := fact.(string); ok {
obsText += fmt.Sprintf("- %s\n", factStr)
obsText += fmt.Sprintf("- %s\n", sanitize.StripSystemXML(factStr))
}
}
obsText += "\n"
}
if narrative, ok := obsMap["narrative"].(string); ok && narrative != "" {
obsText += narrative + "\n\n"
obsText += sanitize.StripSystemXML(narrative) + "\n\n"
}
obsTokens := estimateTokens(obsText)
+1 -1
View File
@@ -15,7 +15,7 @@ require (
github.com/smacker/go-tree-sitter v0.0.0-20240827094217-dd81d9e9be82
github.com/stretchr/testify v1.11.1
github.com/sugarme/tokenizer v0.3.0
github.com/yalue/onnxruntime_go v1.25.0
github.com/yalue/onnxruntime_go v1.27.0
golang.org/x/sync v0.19.0
gorm.io/driver/sqlite v1.6.0
gorm.io/gorm v1.31.1
+2
View File
@@ -54,6 +54,8 @@ github.com/sugarme/regexpset v0.0.0-20200920021344-4d4ec8eaf93c h1:pwb4kNSHb4K89
github.com/sugarme/regexpset v0.0.0-20200920021344-4d4ec8eaf93c/go.mod h1:2gwkXLWbDGUQWeL3RtpCmcY4mzCtU13kb9UsAg9xMaw=
github.com/yalue/onnxruntime_go v1.25.0 h1:nlhVau1BpLZ/BYr+WpPZCJRD/WES0qo6dK7aKyyAs3g=
github.com/yalue/onnxruntime_go v1.25.0/go.mod h1:b4X26A8pekNb1ACJ58wAXgNKeUCGEAQ9dmACut9Sm/4=
github.com/yalue/onnxruntime_go v1.27.0 h1:c1YSgDNtpf0WGtxj3YeRIb8VC5LmM1J+Ve3uHdteC1U=
github.com/yalue/onnxruntime_go v1.27.0/go.mod h1:b4X26A8pekNb1ACJ58wAXgNKeUCGEAQ9dmACut9Sm/4=
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+9 -3
View File
@@ -49,6 +49,10 @@ func BuildObservationPrompt(exec ToolExecution) string {
inputJSON, _ := json.MarshalIndent(toolInput, " ", " ")
outputJSON, _ := json.MarshalIndent(toolOutput, " ", " ")
// Strip system XML artifacts from tool data before building prompt
cleanInput := StripSystemXML(string(inputJSON))
cleanOutput := StripSystemXML(string(outputJSON))
timestamp := time.UnixMilli(exec.CreatedAtEpoch).Format(time.RFC3339)
var sb strings.Builder
@@ -58,8 +62,8 @@ func BuildObservationPrompt(exec ToolExecution) string {
if exec.CWD != "" {
sb.WriteString(fmt.Sprintf(" <working_directory>%s</working_directory>\n", exec.CWD))
}
sb.WriteString(fmt.Sprintf(" <parameters>%s</parameters>\n", truncate(string(inputJSON), 3000)))
sb.WriteString(fmt.Sprintf(" <outcome>%s</outcome>\n", truncate(string(outputJSON), 5000)))
sb.WriteString(fmt.Sprintf(" <parameters>%s</parameters>\n", truncate(cleanInput, 3000)))
sb.WriteString(fmt.Sprintf(" <outcome>%s</outcome>\n", truncate(cleanOutput, 5000)))
sb.WriteString("</observed_from_primary_session>")
return sb.String()
@@ -84,8 +88,10 @@ func BuildSummaryPrompt(req SummaryRequest) string {
sb.WriteString("Write progress notes of what was done, what was learned, and what's next. This is a checkpoint to capture progress so far. The session is ongoing - you may receive more requests and tool executions after this summary. Write \"next_steps\" as the current trajectory of work (what's actively being worked on or coming up next), not as post-session future work. Always write at least a minimal summary explaining current progress, even if work is still in early stages, so that users see a summary output tied to each request.\n\n")
if req.LastAssistantMessage != "" {
// Strip system XML artifacts from captured transcript content
cleanMsg := StripSystemXML(req.LastAssistantMessage)
sb.WriteString("Claude's Full Response to User:\n")
sb.WriteString(truncate(req.LastAssistantMessage, 4000))
sb.WriteString(truncate(cleanMsg, 4000))
sb.WriteString("\n\n")
}
+8
View File
@@ -0,0 +1,8 @@
// Package sdk provides SDK agent integration for claude-mnemonic.
package sdk
import "github.com/lukaszraczylo/claude-mnemonic/pkg/sanitize"
// StripSystemXML removes known Claude Code internal XML blocks from text.
// Delegates to the shared sanitize package.
var StripSystemXML = sanitize.StripSystemXML
+63
View File
@@ -0,0 +1,63 @@
// Package sanitize provides content cleaning utilities for stripping
// Claude Code internal XML artifacts from captured text.
package sanitize
import (
"regexp"
"strings"
)
// systemXMLTags lists Claude Code internal XML tags that should be stripped
// from captured content before processing. These are system-level artifacts
// that pollute observations and summaries when stored.
var systemXMLTags = []string{
// Claude Code task/agent system
"task-notification",
// System reminders injected by Claude Code
"system-reminder",
// Claude-mnemonic's own context injection
"relevant-memory",
// Hook output wrappers
"user-prompt-submit-hook",
// Large output persistence
"persisted-output",
// Tool loading system
"available-deferred-tools",
// Fast mode info
"fast_mode_info",
// Anthropic internal
"antml_thinking",
"antml_function_calls",
}
// systemXMLRegexps are compiled regexps for each tag, built once at init.
var systemXMLRegexps []*regexp.Regexp
func init() {
systemXMLRegexps = make([]*regexp.Regexp, len(systemXMLTags))
for i, tag := range systemXMLTags {
// Match opening tag (with optional attributes), content (including newlines), and closing tag
systemXMLRegexps[i] = regexp.MustCompile(`(?s)<` + regexp.QuoteMeta(tag) + `[^>]*>.*?</` + regexp.QuoteMeta(tag) + `>`)
}
}
// StripSystemXML removes known Claude Code internal XML blocks from text.
// This prevents system artifacts like <task-notification>, <system-reminder>,
// and <relevant-memory> from being stored in observations and summaries.
func StripSystemXML(s string) string {
// Quick check: if no angle brackets, nothing to strip
if !strings.Contains(s, "<") {
return s
}
for _, re := range systemXMLRegexps {
s = re.ReplaceAllString(s, "")
}
// Clean up resulting double-blank-lines from removed blocks
for strings.Contains(s, "\n\n\n") {
s = strings.ReplaceAll(s, "\n\n\n", "\n\n")
}
return strings.TrimSpace(s)
}
+113
View File
@@ -0,0 +1,113 @@
package sanitize
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestStripSystemXML(t *testing.T) {
tests := []struct {
name string
input string
expected string
}{
{
name: "no XML tags",
input: "Hello, this is plain text with no XML.",
expected: "Hello, this is plain text with no XML.",
},
{
name: "empty string",
input: "",
expected: "",
},
{
name: "task-notification block",
input: "Before\n<task-notification>\n<task-id>abc123</task-id>\n<status>completed</status>\n<summary>Agent completed</summary>\n<result>Some result text</result>\n</task-notification>\nAfter",
expected: "Before\n\nAfter",
},
{
name: "system-reminder block",
input: "Content before\n<system-reminder>\nSome system reminder text\n</system-reminder>\nContent after",
expected: "Content before\n\nContent after",
},
{
name: "relevant-memory block",
input: "<relevant-memory>\n# Relevant Knowledge\n## 1. Something\n</relevant-memory>\nActual content",
expected: "Actual content",
},
{
name: "system-reminder with attributes",
input: "Before <system-reminder type=\"hook\">reminder text</system-reminder> After",
expected: "Before After",
},
{
name: "multiple different tags",
input: "Start\n<task-notification><status>done</status></task-notification>\nMiddle\n<system-reminder>reminder</system-reminder>\nEnd",
expected: "Start\n\nMiddle\n\nEnd",
},
{
name: "persisted-output block",
input: "Result: <persisted-output>\nLarge output stored at: /tmp/foo\n</persisted-output> done",
expected: "Result: done",
},
{
name: "available-deferred-tools block",
input: "<available-deferred-tools>\nTool1\nTool2\n</available-deferred-tools>\nUser message",
expected: "User message",
},
{
name: "fast_mode_info block",
input: "Text <fast_mode_info>\nFast mode uses same model\n</fast_mode_info> more text",
expected: "Text more text",
},
{
name: "preserves non-system XML",
input: "<observation><type>bugfix</type><title>Fixed thing</title></observation>",
expected: "<observation><type>bugfix</type><title>Fixed thing</title></observation>",
},
{
name: "no angle brackets fast path",
input: "Just plain text without any special characters",
expected: "Just plain text without any special characters",
},
{
name: "collapses triple newlines",
input: "Before\n<system-reminder>x</system-reminder>\n\n\nAfter",
expected: "Before\n\nAfter",
},
{
name: "real-world task notification",
input: "Here is the analysis:\n<task-notification>\n<task-id>a077fd04aed547ce1</task-id>\n<tool-use-id>toolu_01Kw2GwsArQQR1F9aV3VfzhP</tool-use-id>\n<status>completed</status>\n<summary>Agent \"Analyze agency-agents repo structure\" completed</summary>\n<result>Now I have all the information I need. Let me compile a comprehensive report.\n\n## Agency-Agents Directory Exploration Report\n\n### 1. Agent File Count and Organization\n\n**Total Agent Files (excluding strategy docs):** 61 agents across 9 categories</result>\n</task-notification>\nThe repo has 61 agents.",
expected: "Here is the analysis:\n\nThe repo has 61 agents.",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := StripSystemXML(tt.input)
assert.Equal(t, tt.expected, result)
})
}
}
func BenchmarkStripSystemXML(b *testing.B) {
// Text with no XML (fast path)
b.Run("no_xml", func(b *testing.B) {
text := "This is plain text without any XML tags at all."
b.ResetTimer()
for i := 0; i < b.N; i++ {
StripSystemXML(text)
}
})
// Text with system XML to strip
b.Run("with_xml", func(b *testing.B) {
text := "Before\n<task-notification>\n<task-id>abc</task-id>\n<status>done</status>\n</task-notification>\n<system-reminder>reminder text here</system-reminder>\nAfter"
b.ResetTimer()
for i := 0; i < b.N; i++ {
StripSystemXML(text)
}
})
}
+2 -2
View File
@@ -1,12 +1,12 @@
{
"name": "claude-mnemonic-dashboard",
"version": "v0.10.5-15-g385d05a-dirty",
"version": "v0.11.43-2-g11fd196-dirty",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "claude-mnemonic-dashboard",
"version": "v0.10.5-15-g385d05a-dirty",
"version": "v0.11.43-2-g11fd196-dirty",
"dependencies": {
"vis-data": "^7.1.9",
"vis-network": "^9.1.9",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "claude-mnemonic-dashboard",
"version": "v0.10.5-15-g385d05a-dirty",
"version": "v0.11.43-2-g11fd196-dirty",
"private": true,
"type": "module",
"scripts": {