Add files via upload

This commit is contained in:
公明
2026-07-10 16:40:21 +08:00
committed by GitHub
parent 9dfb9d6c68
commit 225d9ba0d9
3 changed files with 58 additions and 9 deletions
+12 -9
View File
@@ -91,15 +91,15 @@ func NewAgent(cfg *config.OpenAIConfig, agentCfg *config.AgentConfig, mcpServer
llmClient := openai.NewClient(cfg, httpClient, logger)
return &Agent{
openAIClient: llmClient,
config: cfg,
agentConfig: agentCfg,
mcpServer: mcpServer,
externalMCPMgr: externalMCPMgr,
logger: logger,
maxIterations: maxIterations,
toolNameMapping: make(map[string]string), // 初始化工具名称映射
toolDescriptionMode: "short",
openAIClient: llmClient,
config: cfg,
agentConfig: agentCfg,
mcpServer: mcpServer,
externalMCPMgr: externalMCPMgr,
logger: logger,
maxIterations: maxIterations,
toolNameMapping: make(map[string]string), // 初始化工具名称映射
toolDescriptionMode: "short",
}
}
@@ -120,6 +120,9 @@ type ChatMessage struct {
ToolName string `json:"tool_name,omitempty"`
// ReasoningContent 对应 OpenAI/DeepSeek 的 reasoning_content;思考模式 + 工具调用后续跑须回传(见 DeepSeek 文档)。
ReasoningContent string `json:"reasoning_content,omitempty"`
// ModelFacingTrace is runtime-only metadata: true means Content was already the exact
// payload seen at the model boundary and must be restored byte-for-byte.
ModelFacingTrace bool `json:"-"`
}
// MarshalJSON 自定义JSON序列化,将tool_calls中的arguments转换为JSON字符串
+27
View File
@@ -5,6 +5,31 @@ import (
"strings"
)
const ModelFacingTraceVersionKey = "cyberstrike_model_facing_trace_version"
// IsModelFacingTraceJSON reports whether a persisted trace was produced from the final
// model-boundary state. Legacy traces have no version marker and require one-time migration.
func IsModelFacingTraceJSON(traceInputJSON string) bool {
var raw []map[string]interface{}
if err := json.Unmarshal([]byte(strings.TrimSpace(traceInputJSON)), &raw); err != nil {
return false
}
for _, msg := range raw {
extra, _ := msg["extra"].(map[string]interface{})
v, ok := extra[ModelFacingTraceVersionKey]
if !ok {
continue
}
switch n := v.(type) {
case float64:
return n >= 1
case int:
return n >= 1
}
}
return false
}
// ParseTraceMessages 解析落库的 last_react_inputOpenAI 风格 messages JSON 数组)。
func ParseTraceMessages(traceInputJSON string) ([]ChatMessage, error) {
traceInputJSON = strings.TrimSpace(traceInputJSON)
@@ -15,6 +40,7 @@ func ParseTraceMessages(traceInputJSON string) ([]ChatMessage, error) {
if err := json.Unmarshal([]byte(traceInputJSON), &raw); err != nil {
return nil, err
}
modelFacing := IsModelFacingTraceJSON(traceInputJSON)
out := make([]ChatMessage, 0, len(raw))
for _, msgMap := range raw {
msg := ChatMessage{}
@@ -23,6 +49,7 @@ func ParseTraceMessages(traceInputJSON string) ([]ChatMessage, error) {
continue
}
msg.Role = role
msg.ModelFacingTrace = modelFacing
if content, ok := msgMap["content"].(string); ok {
msg.Content = content
}
+19
View File
@@ -55,3 +55,22 @@ func TestMergeAssistantTraceOutput(t *testing.T) {
t.Fatalf("expected merged output, got %q", out[len(out)-1].Content)
}
}
func TestParseTraceMessagesMarksVersionedModelFacingTrace(t *testing.T) {
raw := `[{"role":"system","content":"s","extra":{"cyberstrike_model_facing_trace_version":1}},{"role":"user","content":"u"},{"role":"tool","content":"exact","tool_call_id":"c1"}]`
if !IsModelFacingTraceJSON(raw) {
t.Fatal("versioned trace not detected")
}
msgs, err := ParseTraceMessages(raw)
if err != nil {
t.Fatal(err)
}
for i, msg := range msgs {
if !msg.ModelFacingTrace {
t.Fatalf("message %d missing model-facing marker", i)
}
}
if IsModelFacingTraceJSON(`[{"role":"user","content":"legacy"}]`) {
t.Fatal("legacy trace incorrectly marked model-facing")
}
}