feat(skills): add effective skill resolution and actions (#377)

* feat(skills): add effective skill resolution and actions

* refactor(workspace): normalize skill-related env and prompt

* chore(api): regenerate skills OpenAPI and SDK artifacts

* feat(web): surface effective skill state in console

* test(skills): cover API and runtime effective state

* fix(web): show adopt action for discovered skills

* fix(web): align skill header and show stateful visibility icon

* refactor(web): compact skill metadata on narrow layouts

* fix(web): constrain long skill text in cards

* refactor(skills): narrow default discovery roots

* fix(skills): harden managed skill path validation

* feat: add path in the results of `use_skill`

---------

Co-authored-by: Acbox <acbox0328@gmail.com>
This commit is contained in:
Chrys
2026-04-16 13:50:39 +08:00
committed by GitHub
parent 8e1ed3683f
commit 33e18e7e64
27 changed files with 2223 additions and 209 deletions
+1
View File
@@ -61,6 +61,7 @@ func (*SkillProvider) Tools(_ context.Context, session SessionContext) ([]sdk.To
"skillName": skillName,
"description": skill.Description,
"content": skill.Content,
"path": skill.Path,
}, nil
},
},
+42
View File
@@ -0,0 +1,42 @@
package tools
import (
"context"
"testing"
)
func TestUseSkillReturnsPath(t *testing.T) {
provider := NewSkillProvider(nil)
toolset, err := provider.Tools(context.Background(), SessionContext{
Skills: map[string]SkillDetail{
"pdf": {
Description: "Read PDF instructions",
Content: "Use a PDF-aware workflow.",
Path: "/data/.agents/skills/pdf",
},
},
})
if err != nil {
t.Fatalf("Tools returned error: %v", err)
}
if len(toolset) != 1 {
t.Fatalf("expected 1 tool, got %d", len(toolset))
}
result, err := toolset[0].Execute(nil, map[string]any{
"skillName": "pdf",
"reason": "Need to process a PDF attachment",
})
if err != nil {
t.Fatalf("Execute returned error: %v", err)
}
payload, ok := result.(map[string]any)
if !ok {
t.Fatalf("result type = %T, want map[string]any", result)
}
if got := payload["path"]; got != "/data/.agents/skills/pdf" {
t.Fatalf("path = %#v, want %q", got, "/data/.agents/skills/pdf")
}
}
+1
View File
@@ -15,6 +15,7 @@ import (
type SkillDetail struct {
Description string
Content string
Path string
}
// StreamEventType identifies the kind of stream event emitted by tools.