From 9a677a6265add9a4a5164c2b58ad69923266a0a2 Mon Sep 17 00:00:00 2001 From: mlogclub Date: Sat, 18 Apr 2026 10:54:36 +0800 Subject: [PATCH] refactor(instruction): remove project instruction handling and related tests --- internal/ai/runtime/instruction/assembler.go | 15 +----- .../ai/runtime/instruction/assembler_test.go | 6 +-- .../instruction/project_instruction.go | 16 ------ internal/ai/runtime/instruction/providers.go | 52 ------------------- .../ai/runtime/instruction/providers_test.go | 48 ----------------- internal/ai/runtime/instruction/service.go | 11 ---- .../impl/callbacks/runlog_callback.go | 1 - .../internal/impl/callbacks/trace_callback.go | 2 - .../internal/impl/factory/agent_factory.go | 2 +- .../factory/agent_handler_service_test.go | 7 ++- .../internal/impl/factory/tool_helpers.go | 1 - .../impl/factory/tool_helpers_test.go | 5 +- 12 files changed, 9 insertions(+), 157 deletions(-) delete mode 100644 internal/ai/runtime/instruction/project_instruction.go delete mode 100644 internal/ai/runtime/instruction/providers_test.go diff --git a/internal/ai/runtime/instruction/assembler.go b/internal/ai/runtime/instruction/assembler.go index 81f63a6..778e8ad 100644 --- a/internal/ai/runtime/instruction/assembler.go +++ b/internal/ai/runtime/instruction/assembler.go @@ -20,12 +20,10 @@ type AssemblerInput struct { GovernanceInstruction string SkillInstruction string ToolAppendices []string - ProjectInstruction string } type AssemblySummary struct { SectionTitles []string - HasProjectRule bool HasGovernanceRule bool HasAgentRule bool HasSkillRule bool @@ -46,17 +44,8 @@ func (a *Assembler) Build(input AssemblerInput) string { } func (a *Assembler) Assemble(input AssemblerInput) AssemblyResult { - parts := make([]string, 0, 5) - summary := AssemblySummary{SectionTitles: make([]string, 0, 5)} - projectInstruction := strings.TrimSpace(input.ProjectInstruction) - if projectInstruction == "" { - projectInstruction = strings.TrimSpace(DefaultProjectInstruction) - } - if projectInstruction != "" { - parts = append(parts, buildInstructionSection("项目级规则", projectInstruction)) - summary.HasProjectRule = true - summary.SectionTitles = append(summary.SectionTitles, "项目级规则") - } + parts := make([]string, 0, 4) + summary := AssemblySummary{SectionTitles: make([]string, 0, 4)} governanceInstruction := strings.TrimSpace(input.GovernanceInstruction) if governanceInstruction == "" && a != nil { governanceInstruction = strings.TrimSpace(a.governanceInstruction) diff --git a/internal/ai/runtime/instruction/assembler_test.go b/internal/ai/runtime/instruction/assembler_test.go index fbf9d91..38979d2 100644 --- a/internal/ai/runtime/instruction/assembler_test.go +++ b/internal/ai/runtime/instruction/assembler_test.go @@ -7,15 +7,11 @@ import ( func TestAssemblerRespectsProvidedSources(t *testing.T) { result := NewAssembler().Assemble(AssemblerInput{ - ProjectInstruction: "project-rule", GovernanceInstruction: "governance-rule", AgentInstruction: "agent-rule", SkillInstruction: "skill-rule", ToolAppendices: []string{"tool-rule-1", "tool-rule-2"}, }) - if !strings.Contains(result.Text, "项目级规则:\nproject-rule") { - t.Fatalf("missing project instruction: %s", result.Text) - } if !strings.Contains(result.Text, "系统治理规则:\ngovernance-rule") { t.Fatalf("missing governance instruction: %s", result.Text) } @@ -25,7 +21,7 @@ func TestAssemblerRespectsProvidedSources(t *testing.T) { if !strings.Contains(result.Text, "工具补充规则:\ntool-rule-1") { t.Fatalf("missing tool appendix: %s", result.Text) } - if !result.Summary.HasProjectRule || !result.Summary.HasGovernanceRule || !result.Summary.HasAgentRule || !result.Summary.HasSkillRule || !result.Summary.HasToolRule { + if !result.Summary.HasGovernanceRule || !result.Summary.HasAgentRule || !result.Summary.HasSkillRule || !result.Summary.HasToolRule { t.Fatalf("unexpected summary: %#v", result.Summary) } } diff --git a/internal/ai/runtime/instruction/project_instruction.go b/internal/ai/runtime/instruction/project_instruction.go deleted file mode 100644 index 42ee49e..0000000 --- a/internal/ai/runtime/instruction/project_instruction.go +++ /dev/null @@ -1,16 +0,0 @@ -package instruction - -// DefaultProjectInstruction 为当前项目统一注入的全局项目规则。 -// -// 默认回退到内置常量;运行时优先由 ProjectInstructionProvider 读取仓库中的 AGENTS.md。 -// TODO 这里是做什么的?为什么不直接读取AIAgent的? -const DefaultProjectInstruction = `# AGENTS.md - -本文件定义本项目内 AI Agent 的强制开发规则。除非用户明确要求偏离,否则必须遵循。 - -## 1. 基本原则 - -- 适用范围:仓库根目录及所有子目录 -- 优先级:用户明确指令 > 本文件 > 默认实现习惯 -- 若与用户要求冲突:先执行用户要求,并在变更说明中标注偏离点 -` diff --git a/internal/ai/runtime/instruction/providers.go b/internal/ai/runtime/instruction/providers.go index db469db..2c0cd59 100644 --- a/internal/ai/runtime/instruction/providers.go +++ b/internal/ai/runtime/instruction/providers.go @@ -1,8 +1,6 @@ package instruction import ( - "os" - "path/filepath" "strings" runtimetooling "cs-agent/internal/ai/runtime/tooling" @@ -10,56 +8,6 @@ import ( "cs-agent/internal/pkg/toolx" ) -type ProjectInstructionProvider struct { - fileName string -} - -func NewProjectInstructionProvider() *ProjectInstructionProvider { - return &ProjectInstructionProvider{fileName: "AGENTS.md"} -} - -func (p *ProjectInstructionProvider) Resolve() string { - if text := p.loadFromFile(); text != "" { - return text - } - return strings.TrimSpace(DefaultProjectInstruction) -} - -func (p *ProjectInstructionProvider) loadFromFile() string { - path := p.resolvePath() - if path == "" { - return "" - } - data, err := os.ReadFile(path) - if err != nil { - return "" - } - return strings.TrimSpace(string(data)) -} - -func (p *ProjectInstructionProvider) resolvePath() string { - fileName := "AGENTS.md" - if p != nil && strings.TrimSpace(p.fileName) != "" { - fileName = strings.TrimSpace(p.fileName) - } - wd, err := os.Getwd() - if err != nil { - return "" - } - dir := wd - for { - candidate := filepath.Join(dir, fileName) - if stat, statErr := os.Stat(candidate); statErr == nil && !stat.IsDir() { - return candidate - } - parent := filepath.Dir(dir) - if parent == dir { - return "" - } - dir = parent - } -} - type ToolAppendixProvider struct{} func NewToolAppendixProvider() *ToolAppendixProvider { diff --git a/internal/ai/runtime/instruction/providers_test.go b/internal/ai/runtime/instruction/providers_test.go deleted file mode 100644 index 3eef409..0000000 --- a/internal/ai/runtime/instruction/providers_test.go +++ /dev/null @@ -1,48 +0,0 @@ -package instruction - -import ( - "os" - "path/filepath" - "strings" - "testing" -) - -func TestProjectInstructionProviderResolveFromAgentsFile(t *testing.T) { - tmpDir := t.TempDir() - nestedDir := filepath.Join(tmpDir, "nested", "child") - if err := os.MkdirAll(nestedDir, 0o755); err != nil { - t.Fatalf("mkdir failed: %v", err) - } - content := "# AGENTS.md\n\nfrom temp file" - if err := os.WriteFile(filepath.Join(tmpDir, "AGENTS.md"), []byte(content), 0o644); err != nil { - t.Fatalf("write file failed: %v", err) - } - wd, err := os.Getwd() - if err != nil { - t.Fatalf("getwd failed: %v", err) - } - defer func() { _ = os.Chdir(wd) }() - if err := os.Chdir(nestedDir); err != nil { - t.Fatalf("chdir failed: %v", err) - } - got := NewProjectInstructionProvider().Resolve() - if !strings.Contains(got, "from temp file") { - t.Fatalf("expected provider to load AGENTS.md from file, got: %s", got) - } -} - -func TestProjectInstructionProviderFallbacksToDefault(t *testing.T) { - tmpDir := t.TempDir() - wd, err := os.Getwd() - if err != nil { - t.Fatalf("getwd failed: %v", err) - } - defer func() { _ = os.Chdir(wd) }() - if err := os.Chdir(tmpDir); err != nil { - t.Fatalf("chdir failed: %v", err) - } - got := NewProjectInstructionProvider().Resolve() - if !strings.Contains(got, "本文件定义本项目内 AI Agent 的强制开发规则") { - t.Fatalf("expected fallback project instruction, got: %s", got) - } -} diff --git a/internal/ai/runtime/instruction/service.go b/internal/ai/runtime/instruction/service.go index bb03aef..eca03f7 100644 --- a/internal/ai/runtime/instruction/service.go +++ b/internal/ai/runtime/instruction/service.go @@ -9,7 +9,6 @@ import ( type Service struct { assembler *Assembler - projectInstructionProvider *ProjectInstructionProvider governanceInstructionProvider *GovernanceInstructionProvider skillInstructionProvider *SkillInstructionProvider toolAppendixProvider *ToolAppendixProvider @@ -17,7 +16,6 @@ type Service struct { func NewService( assembler *Assembler, - projectProvider *ProjectInstructionProvider, governanceProvider *GovernanceInstructionProvider, skillProvider *SkillInstructionProvider, toolProvider *ToolAppendixProvider, @@ -25,9 +23,6 @@ func NewService( if assembler == nil { assembler = NewAssembler() } - if projectProvider == nil { - projectProvider = NewProjectInstructionProvider() - } if governanceProvider == nil { governanceProvider = NewGovernanceInstructionProvider() } @@ -39,7 +34,6 @@ func NewService( } return &Service{ assembler: assembler, - projectInstructionProvider: projectProvider, governanceInstructionProvider: governanceProvider, skillInstructionProvider: skillProvider, toolAppendixProvider: toolProvider, @@ -52,13 +46,9 @@ func (s *Service) Build( toolDefinitions []runtimetooling.MCPToolDefinition, extraToolCodes map[string]string, ) AssemblyResult { - projectInstruction := "" governanceInstruction := "" skillInstruction := "" toolAppendices := make([]string, 0) - if s != nil && s.projectInstructionProvider != nil { - projectInstruction = s.projectInstructionProvider.Resolve() - } if s != nil && s.governanceInstructionProvider != nil { governanceInstruction = s.governanceInstructionProvider.Resolve() } @@ -77,6 +67,5 @@ func (s *Service) Build( GovernanceInstruction: governanceInstruction, SkillInstruction: skillInstruction, ToolAppendices: toolAppendices, - ProjectInstruction: projectInstruction, }) } diff --git a/internal/ai/runtime/internal/impl/callbacks/runlog_callback.go b/internal/ai/runtime/internal/impl/callbacks/runlog_callback.go index 4e39e1f..3427591 100644 --- a/internal/ai/runtime/internal/impl/callbacks/runlog_callback.go +++ b/internal/ai/runtime/internal/impl/callbacks/runlog_callback.go @@ -48,7 +48,6 @@ func (c *RuntimeTraceCollector) SetInstructionSummary(summary InstructionTraceSu c.mu.Lock() defer c.mu.Unlock() c.Data.Instruction.SectionTitles = append([]string(nil), summary.SectionTitles...) - c.Data.Instruction.HasProjectRule = summary.HasProjectRule c.Data.Instruction.HasGovernanceRule = summary.HasGovernanceRule c.Data.Instruction.HasAgentRule = summary.HasAgentRule c.Data.Instruction.HasSkillRule = summary.HasSkillRule diff --git a/internal/ai/runtime/internal/impl/callbacks/trace_callback.go b/internal/ai/runtime/internal/impl/callbacks/trace_callback.go index d448d6f..a97a08c 100644 --- a/internal/ai/runtime/internal/impl/callbacks/trace_callback.go +++ b/internal/ai/runtime/internal/impl/callbacks/trace_callback.go @@ -71,7 +71,6 @@ type RetrieverPolicyTraceItem struct { type InstructionTraceSummary struct { SectionTitles []string - HasProjectRule bool HasGovernanceRule bool HasAgentRule bool HasSkillRule bool @@ -93,7 +92,6 @@ type RuntimeTraceData struct { } `json:"model"` Instruction struct { SectionTitles []string `json:"sectionTitles,omitempty"` - HasProjectRule bool `json:"hasProjectRule,omitempty"` HasGovernanceRule bool `json:"hasGovernanceRule,omitempty"` HasAgentRule bool `json:"hasAgentRule,omitempty"` HasSkillRule bool `json:"hasSkillRule,omitempty"` diff --git a/internal/ai/runtime/internal/impl/factory/agent_factory.go b/internal/ai/runtime/internal/impl/factory/agent_factory.go index 631d551..26d78f4 100644 --- a/internal/ai/runtime/internal/impl/factory/agent_factory.go +++ b/internal/ai/runtime/internal/impl/factory/agent_factory.go @@ -56,7 +56,7 @@ func NewAgentFactory() *AgentFactory { return &AgentFactory{ chatModelFactory: NewChatModelFactory(), toolFactory: NewToolFactory(), - instructionService: runtimeinstruction.NewService(nil, nil, nil, nil, nil), + instructionService: runtimeinstruction.NewService(nil, nil, nil, nil), handlerService: NewAgentHandlerService(nil), } } diff --git a/internal/ai/runtime/internal/impl/factory/agent_handler_service_test.go b/internal/ai/runtime/internal/impl/factory/agent_handler_service_test.go index e24b1d6..9192f1e 100644 --- a/internal/ai/runtime/internal/impl/factory/agent_handler_service_test.go +++ b/internal/ai/runtime/internal/impl/factory/agent_handler_service_test.go @@ -14,8 +14,7 @@ func TestAgentHandlerServiceBuildWithCollectorOnly(t *testing.T) { handlers, err := service.Build(context.Background(), BuildAgentHandlersInput{ Collector: collector, InstructionSummary: einocallbacks.InstructionTraceSummary{ - SectionTitles: []string{"项目级规则", "系统治理规则"}, - HasProjectRule: true, + SectionTitles: []string{"系统治理规则"}, HasGovernanceRule: true, }, }) @@ -25,10 +24,10 @@ func TestAgentHandlerServiceBuildWithCollectorOnly(t *testing.T) { if len(handlers) != 1 { t.Fatalf("expected 1 handler, got %d", len(handlers)) } - if !collector.Data.Instruction.HasProjectRule || !collector.Data.Instruction.HasGovernanceRule { + if !collector.Data.Instruction.HasGovernanceRule { t.Fatalf("instruction summary was not written to collector: %#v", collector.Data.Instruction) } - if len(collector.Data.Instruction.SectionTitles) != 2 { + if len(collector.Data.Instruction.SectionTitles) != 1 { t.Fatalf("unexpected section titles: %#v", collector.Data.Instruction.SectionTitles) } } diff --git a/internal/ai/runtime/internal/impl/factory/tool_helpers.go b/internal/ai/runtime/internal/impl/factory/tool_helpers.go index e01ef1e..2c1aab8 100644 --- a/internal/ai/runtime/internal/impl/factory/tool_helpers.go +++ b/internal/ai/runtime/internal/impl/factory/tool_helpers.go @@ -15,7 +15,6 @@ import ( func buildInstructionTraceSummary(summary runtimeinstruction.AssemblySummary) einocallbacks.InstructionTraceSummary { return einocallbacks.InstructionTraceSummary{ SectionTitles: append([]string(nil), summary.SectionTitles...), - HasProjectRule: summary.HasProjectRule, HasGovernanceRule: summary.HasGovernanceRule, HasAgentRule: summary.HasAgentRule, HasSkillRule: summary.HasSkillRule, diff --git a/internal/ai/runtime/internal/impl/factory/tool_helpers_test.go b/internal/ai/runtime/internal/impl/factory/tool_helpers_test.go index 6660434..6efb632 100644 --- a/internal/ai/runtime/internal/impl/factory/tool_helpers_test.go +++ b/internal/ai/runtime/internal/impl/factory/tool_helpers_test.go @@ -8,8 +8,7 @@ import ( func TestBuildInstructionTraceSummary(t *testing.T) { got := buildInstructionTraceSummary(runtimeinstruction.AssemblySummary{ - SectionTitles: []string{"项目级规则", "当前技能上下文"}, - HasProjectRule: true, + SectionTitles: []string{"系统治理规则", "当前技能上下文"}, HasGovernanceRule: true, HasAgentRule: true, HasSkillRule: true, @@ -19,7 +18,7 @@ func TestBuildInstructionTraceSummary(t *testing.T) { if len(got.SectionTitles) != 2 { t.Fatalf("unexpected section titles: %#v", got.SectionTitles) } - if !got.HasProjectRule || !got.HasGovernanceRule || !got.HasAgentRule || !got.HasSkillRule { + if !got.HasGovernanceRule || !got.HasAgentRule || !got.HasSkillRule { t.Fatalf("unexpected summary flags: %#v", got) } if got.HasToolRule {