feat: RAG, memory, plugins, lessons, file editor, split panes, Markdown rendering, PWA + UI overhaul
All checks were successful
Stable Release / stable (push) Successful in 1m34s

Major additions:
- RAG pipeline (indexing, chunking, search) with sidebar upload button
- Memory system with CRUD API
- Plugins and lessons modules
- MCP discovery and MCP server
- Advanced skills (auto-create, conditional, improver)
- Agent browser/image support, delegate, sessions
- File editor with CodeMirror in split panes
- Markdown rendering via react-markdown + KaTeX + highlight.js
- Raw markdown toggle
- PWA manifest + service worker
- Extension UI redesign with new design tokens and studio-style chat
- Pipeline API for chat streaming
- Mobile responsive layout

💘 Generated with Crush

Assisted-by: GLM-5.1 via Crush <crush@charm.land>
This commit is contained in:
Augustin
2026-04-27 21:01:08 +02:00
parent 62c20eb174
commit 4523bbd42c
50 changed files with 11144 additions and 469 deletions

View File

@@ -0,0 +1,125 @@
package skills
import (
"strings"
)
type ActivationResult struct {
Active bool
Reason string
Skill *Skill
}
func CheckActivation(skill *Skill, availableTools []string) ActivationResult {
if len(skill.RequiresTools) == 0 && len(skill.FallbackForTools) == 0 {
return ActivationResult{
Active: true,
Reason: "no activation conditions",
Skill: skill,
}
}
toolSet := make(map[string]bool, len(availableTools))
for _, t := range availableTools {
toolSet[strings.ToLower(t)] = true
}
if len(skill.RequiresTools) > 0 {
for _, req := range skill.RequiresTools {
if !toolSet[strings.ToLower(req)] {
return ActivationResult{
Active: false,
Reason: "missing required tool: " + req,
Skill: skill,
}
}
}
return ActivationResult{
Active: true,
Reason: "all required tools available",
Skill: skill,
}
}
if len(skill.FallbackForTools) > 0 {
allPresent := true
for _, fb := range skill.FallbackForTools {
if !toolSet[strings.ToLower(fb)] {
allPresent = false
break
}
}
if allPresent {
return ActivationResult{
Active: false,
Reason: "primary tools available, fallback not needed",
Skill: skill,
}
}
return ActivationResult{
Active: true,
Reason: "primary tools absent, activating as fallback",
Skill: skill,
}
}
return ActivationResult{Active: true, Skill: skill}
}
func FilterActiveSkills(skillsList []Skill, availableTools []string) []Skill {
var active []Skill
for i := range skillsList {
result := CheckActivation(&skillsList[i], availableTools)
if result.Active {
active = append(active, skillsList[i])
}
}
return active
}
func GroupByReadiness(skillsList []Skill, availableTools []string) (available, needsSetup, unsupported []Skill) {
toolSet := make(map[string]bool, len(availableTools))
for _, t := range availableTools {
toolSet[strings.ToLower(t)] = true
}
for i := range skillsList {
s := &skillsList[i]
if len(s.RequiresTools) == 0 && len(s.FallbackForTools) == 0 {
missing := CheckDependencies(s)
if len(missing) == 0 {
available = append(available, *s)
} else {
needsSetup = append(needsSetup, *s)
}
continue
}
allReqMet := true
for _, req := range s.RequiresTools {
if !toolSet[strings.ToLower(req)] {
allReqMet = false
break
}
}
if allReqMet && len(s.RequiresTools) > 0 {
available = append(available, *s)
} else if !allReqMet && len(s.RequiresTools) > 0 {
unsupported = append(unsupported, *s)
}
if len(s.FallbackForTools) > 0 {
anyMissing := false
for _, fb := range s.FallbackForTools {
if !toolSet[strings.ToLower(fb)] {
anyMissing = true
break
}
}
if anyMissing {
available = append(available, *s)
}
}
}
return
}