Merge remote-tracking branch 'origin/pr-577' into codex/pr-557-589-security-integration

This commit is contained in:
ddCat
2026-09-22 11:05:08 +08:00
3 changed files with 32 additions and 4 deletions

View File

@@ -215,16 +215,28 @@ func TestCloudAgentAnnotationRenderFeedsControlledTransientReference(t *testing.
}
func TestCloudAgentPolicyPublishesSkillManifestWithoutInliningSkillBody(t *testing.T) {
skill := cloudAgentSkill{ID: "skill-1", Name: "任务技能", Version: "v1", Hash: agentProfileHash("skill"), Instruction: "PRIVATE_SKILL_BODY", Files: map[string]string{"references/a.md": "A"}}
skill := cloudAgentSkill{ID: "skill-1", Name: "任务技能", Description: "当用户要写短剧剧本时调用", Version: "v1", Hash: agentProfileHash("skill"), Instruction: "PRIVATE_SKILL_BODY", Files: map[string]string{"references/a.md": "A"}}
text, _, err := compileCloudAgentPolicies(agentTestRequest(), []cloudAgentSkill{skill}, "", cloudAgentProfileSnapshot{Revision: agentProfileRevision(nil), Hash: agentProfileHash("")})
if err != nil {
t.Fatal(err)
}
if strings.Contains(text, skill.Instruction) || !strings.Contains(text, `"entryPath":"SKILL.md"`) || !strings.Contains(text, `"files":["SKILL.md","references/a.md"]`) {
if strings.Contains(text, skill.Instruction) || !strings.Contains(text, `"entryPath":"SKILL.md"`) || !strings.Contains(text, `"files":["SKILL.md","references/a.md"]`) || !strings.Contains(text, `"description":"当用户要写短剧剧本时调用"`) {
t.Fatalf("compiled policy did not publish a safe on-demand skill manifest: %s", text)
}
}
func TestCloudAgentPolicyTruncatesOversizedSkillDescription(t *testing.T) {
long := strings.Repeat("描", 600)
skill := cloudAgentSkill{ID: "skill-2", Name: "长描述技能", Description: long, Version: "v1", Hash: agentProfileHash("skill2")}
text, _, err := compileCloudAgentPolicies(agentTestRequest(), []cloudAgentSkill{skill}, "", cloudAgentProfileSnapshot{Revision: agentProfileRevision(nil), Hash: agentProfileHash("")})
if err != nil {
t.Fatal(err)
}
if strings.Contains(text, long) || !strings.Contains(text, strings.Repeat("描", 500)+"…") {
t.Fatalf("oversized skill description was not capped at 500 runes: %s", text)
}
}
func TestCloudAgentPolicyPublishesCapabilityRoutingGuide(t *testing.T) {
text, _, err := compileCloudAgentPolicies(agentTestRequest(), nil, "", cloudAgentProfileSnapshot{Revision: agentProfileRevision(nil), Hash: agentProfileHash("")})
if err != nil {

View File

@@ -84,6 +84,19 @@ func cloudAgentCapabilityGuide() string {
return b.String()
}
// cloudAgentSkillManifestDescription bounds the system prompt: the description
// is author-supplied public metadata, so it is trimmed and capped before it
// enters the compiled policy.
func cloudAgentSkillManifestDescription(description string) string {
const maxRunes = 500
trimmed := strings.TrimSpace(description)
if utf8.RuneCountInString(trimmed) <= maxRunes {
return trimmed
}
runes := []rune(trimmed)
return strings.TrimSpace(string(runes[:maxRunes])) + "…"
}
func compileCloudAgentPolicies(req CloudAgentRequest, skills []cloudAgentSkill, canvasSummary string, profile cloudAgentProfileSnapshot, anchors ...cloudAgentCreativeAnchor) (string, cloudAgentPolicySnapshot, error) {
system, media, err := prompts.LoadAgentPolicies()
if err != nil {
@@ -121,7 +134,7 @@ func compileCloudAgentPolicies(req CloudAgentRequest, skills []cloudAgentSkill,
}
manifests := make([]map[string]any, 0, len(skills))
for _, skill := range skills {
manifests = append(manifests, map[string]any{"skillId": skill.ID, "name": skill.Name, "version": skill.Version, "hash": skill.Hash, "entryPath": cloudAgentSkillEntryPath, "files": cloudAgentSkillPaths(skill)})
manifests = append(manifests, map[string]any{"skillId": skill.ID, "name": skill.Name, "description": cloudAgentSkillManifestDescription(skill.Description), "version": skill.Version, "hash": skill.Hash, "entryPath": cloudAgentSkillEntryPath, "files": cloudAgentSkillPaths(skill)})
}
context["skills"] = manifests
layers := make([]map[string]any, 0, len(profile.Layers))

View File

@@ -22,6 +22,7 @@ import (
type cloudAgentSkill struct {
ID string `json:"id"`
Name string `json:"name"`
Description string `json:"description,omitempty"`
Version string `json:"version"`
Hash string `json:"hash"`
Instruction string `json:"instruction,omitempty"`
@@ -60,7 +61,9 @@ func (s *Service) cloudAgentSkills(userID string, ids []string) ([]cloudAgentSki
}
// Skill content is loaded only after the model explicitly calls
// skill_read_file; keep the run context to stable metadata and paths.
snapshot := cloudAgentSkill{ID: id, Name: skill.SkillName, Version: skill.VersionID, Hash: skill.ContentHash, Files: map[string]string{cloudAgentSkillEntryPath: ""}}
// The description is public metadata (market listing) and lets the
// model route between activated skills without reading any body.
snapshot := cloudAgentSkill{ID: id, Name: skill.SkillName, Description: skill.Description, Version: skill.VersionID, Hash: skill.ContentHash, Files: map[string]string{cloudAgentSkillEntryPath: ""}}
files, err := s.SkillPackageFiles(userID, id)
if err != nil {
return nil, err